Skip to content

Commit

Permalink
Support custom pkg entrypoints, useful for Svelte projects (#1457)
Browse files Browse the repository at this point in the history
* support passing custom package manifest entrypoints to esinstall

* support custom lookup entrypoint fields
  • Loading branch information
FredKSchott authored Oct 31, 2020
1 parent eda2e94 commit 29558d8
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 7 deletions.
3 changes: 3 additions & 0 deletions docs/10-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ Options:
- _NOTE: This is an advanced feature, and may not do what you want! Bare imports are not supported in any major browser, so an ignored import will usually fail when sent directly to the browser._
- Mark some imports as external. Snowpack won't install them and will ignore them when resolving imports.
- Example: `"externalPackage": ["fs"]`
- **`installOptions.packageLookupFields`** | `string[]`
- Set custom lookup fields for dependency `package.json` file entrypoints, in addition to the defaults like "module", "main", etc. Useful for package ecosystems like Svelte where dependencies aren't shipped as traditional JavaScript.
- Example: `"packageLookupFields": ["svelte"]`
- **`installOptions.rollup`** | `Object`
- Snowpack uses Rollup internally to install your packages. This `rollup` config option gives you deeper control over the internal rollup configuration that we use.
- **`installOptions.rollup.plugins`** - Specify [Custom Rollup plugins](#installing-non-js-packages) if you are dealing with non-standard files.
Expand Down
18 changes: 12 additions & 6 deletions esinstall/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import {
findMatchingAliasEntry,
getWebDependencyName,
isPackageAliasEntry,
isTruthy,
MISSING_PLUGIN_SUGGESTIONS,
parsePackageImportSpecifier,
resolveDependencyManifest,
Expand Down Expand Up @@ -90,7 +89,10 @@ function isImportOfPackage(importUrl: string, packageName: string) {
* Follows logic similar to Node's resolution logic, but using a package.json's ESM "module"
* field instead of the CJS "main" field.
*/
function resolveWebDependency(dep: string, {cwd}: {cwd: string}): DependencyLoc {
function resolveWebDependency(
dep: string,
{cwd, packageLookupFields}: {cwd: string; packageLookupFields: string[]},
): DependencyLoc {
// if dep points directly to a file within a package, return that reference.
// No other lookup required.
if (path.extname(dep) && !validatePackageName(dep).validForNewPackages) {
Expand Down Expand Up @@ -156,9 +158,9 @@ function resolveWebDependency(dep: string, {cwd}: {cwd: string}): DependencyLoc
`React workaround packages no longer needed! Revert back to the official React & React-DOM packages.`,
);
}
let foundEntrypoint: string =
depManifest['browser:module'] || depManifest.module || depManifest['main:esnext'];

let foundEntrypoint: any = [...packageLookupFields, 'browser:module', 'module', 'main:esnext']
.map((e) => depManifest[e])
.find(Boolean);
if (!foundEntrypoint && !BROKEN_BROWSER_ENTRYPOINT.includes(packageName)) {
foundEntrypoint = depManifest.browser;
}
Expand Down Expand Up @@ -227,6 +229,7 @@ interface InstallOptions {
polyfillNode: boolean;
sourceMap?: boolean | 'inline';
externalPackage: string[];
packageLookupFields: string[];
namedExports: string[];
rollup: {
context?: string;
Expand All @@ -250,6 +253,7 @@ function setOptionDefaults(_options: PublicInstallOptions): InstallOptions {
dest: 'web_modules',
externalPackage: [],
polyfillNode: false,
packageLookupFields: [],
env: {},
namedExports: [],
rollup: {
Expand Down Expand Up @@ -279,6 +283,7 @@ export async function install(
rollup: userDefinedRollup,
treeshake: isTreeshake,
polyfillNode,
packageLookupFields,
} = setOptionDefaults(_options);
const env = generateEnvObject(userEnv);

Expand Down Expand Up @@ -316,6 +321,7 @@ export async function install(
try {
const resolvedResult = resolveWebDependency(installSpecifier, {
cwd,
packageLookupFields,
});
if (resolvedResult.type === 'JS') {
installEntrypoints[targetName] = resolvedResult.loc;
Expand Down Expand Up @@ -366,7 +372,7 @@ ${colors.dim(
}),
rollupPluginCatchFetch(),
rollupPluginNodeResolve({
mainFields: ['browser:module', 'module', 'browser', 'main'].filter(isTruthy),
mainFields: ['browser:module', 'module', 'browser', 'main'],
extensions: ['.mjs', '.cjs', '.js', '.json'], // Default: [ '.mjs', '.js', '.json', '.node' ]
// whether to prefer built-in modules (e.g. `fs`, `path`) or local ones with the same names
preferBuiltins: true, // Default: true
Expand Down
4 changes: 3 additions & 1 deletion snowpack/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ const DEFAULT_CONFIG: Partial<SnowpackConfig> = {
alias: {},
scripts: {},
exclude: [],
installOptions: {},
installOptions: {
packageLookupFields: [],
},
devOptions: {
secure: false,
hostname: 'localhost',
Expand Down
26 changes: 26 additions & 0 deletions test/esinstall/config-package-lookup-fields/__snapshots__
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`snowpack install config-package-lookup-fields: allFiles 1`] = `
Array [
"import-map.json",
"some-svelte-package.js",
]
`;

exports[`snowpack install config-package-lookup-fields: cli output 1`] = `
"[snowpack] installing dependencies...
[snowpack] ✔ install complete!
[snowpack]
⦿ web_modules/ size gzip brotli
└─ some-svelte-package.js XXXX KB XXXX KB XXXX KB"
`;

exports[`snowpack install config-package-lookup-fields: web_modules/import-map.json 1`] = `
"{
\\"imports\\": {
\\"some-svelte-package\\": \\"./some-svelte-package.js\\"
}
}"
`;

exports[`snowpack install config-package-lookup-fields: web_modules/some-svelte-package.js 1`] = `"console.log('TEST: THIS IS THE GOOD ENTRYPOINT');"`;
20 changes: 20 additions & 0 deletions test/esinstall/config-package-lookup-fields/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"private": true,
"version": "1.0.1",
"name": "@snowpack/test-config-package-lookup-fields",
"description": "Handle custom packageLookupFields",
"scripts": {
"testinstall": "snowpack"
},
"snowpack": {
"installOptions": {
"packageLookupFields": ["svelte"]
}
},
"dependencies": {
"some-svelte-package": "file:./packages/some-svelte-package"
},
"devDependencies": {
"snowpack": "^2.14.3"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('TEST: THIS IS THE BAD ENTRYPOINT');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('TEST: THIS IS THE GOOD ENTRYPOINT');
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"version": "1.0.0",
"name": "some-svelte-package",
"svelte": "good.js",
"module": "bad.js"
}
1 change: 1 addition & 0 deletions test/esinstall/config-package-lookup-fields/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import 'some-svelte-package';
3 changes: 3 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13457,6 +13457,9 @@ solid-js@^0.16.7:
resolved "https://registry.yarnpkg.com/solid-js/-/solid-js-0.16.14.tgz#098aea093d1f1660c3572eda5af085e5d0cc2f20"
integrity sha512-fdkzrseYaileVAHJAmGRXBrq6Uyd7zwGK53T+QnKTlvd5hhPSh5i2W8vny1HycHTXZ3v8oms/2H2Gj3/cVfVqQ==

"some-svelte-package@file:./test/esinstall/config-package-lookup-fields/packages/some-svelte-package":
version "1.0.0"

sort-keys-length@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188"
Expand Down

1 comment on commit 29558d8

@vercel
Copy link

@vercel vercel bot commented on 29558d8 Oct 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.