Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify. cleanup, enhance snowpack internals #2707

Merged
merged 40 commits into from Mar 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ab38057
refactor snowpack internals
FredKSchott Feb 22, 2021
c8d5062
fix import proxies
FredKSchott Feb 24, 2021
7a929ba
fix bad default import scanner
FredKSchott Feb 24, 2021
d876119
add tslib polyfill
FredKSchott Feb 24, 2021
7b1bc00
Offical wip new pkg (#2726)
daydayhappychao Feb 24, 2021
8f26514
clean up snowpack symlink warning
FredKSchott Feb 24, 2021
e4f931a
add support for imports of external packages
FredKSchott Feb 24, 2021
95e8672
add workspaceRoot config
FredKSchott Feb 24, 2021
159d50a
lint fix
FredKSchott Feb 24, 2021
adf2580
treat namedExports as non-ESM by default
FredKSchott Feb 24, 2021
892834b
add cjs<>esm interop improvements
FredKSchott Feb 24, 2021
72d5dd8
actually memoize the results
FredKSchott Feb 24, 2021
600cbaf
add back fsevents check
FredKSchott Feb 24, 2021
5ad4565
add alias support, better symlink support
FredKSchott Feb 25, 2021
d26e13d
add support for buffer loading
FredKSchott Feb 25, 2021
a341e48
fix baseUrl in proxies
FredKSchott Feb 25, 2021
d493acd
add source to entrypoints
FredKSchott Feb 25, 2021
31f1a4a
small fixes based on pr feedback
FredKSchott Feb 28, 2021
eb0fd54
lint fix, and stop ignoring empty files
FredKSchott Feb 28, 2021
a3683ff
add better empty file handling
FredKSchott Feb 28, 2021
7371bdd
update test
FredKSchott Feb 28, 2021
5b17018
fix bad variable scoping
FredKSchott Feb 28, 2021
72e076f
make hmr optional
FredKSchott Feb 28, 2021
20ee69e
move hmr logic into seperate file
FredKSchott Feb 28, 2021
c424ed3
small hmrengine optional fix
FredKSchott Feb 28, 2021
4f93348
format
FredKSchott Feb 28, 2021
2145e29
wip: new dashboard output
FredKSchott Feb 28, 2021
17f171e
new dashboard output
FredKSchott Feb 28, 2021
c67883c
add never peer packages to bundle common polyfills
FredKSchott Feb 28, 2021
510e0fe
add proxy import support for cross-package imports
FredKSchott Feb 28, 2021
d5b2c05
a bit of logging cleanup
FredKSchott Feb 28, 2021
b743c11
add fix for source map exact matches
FredKSchott Feb 28, 2021
ab57bc7
update with feedback, get build watch better
FredKSchott Mar 1, 2021
cd49f8e
add a warning if you try to link a mounted file
FredKSchott Mar 1, 2021
1069e26
include non-proxy files in final build
FredKSchott Mar 1, 2021
1e82589
fix css issue
FredKSchott Mar 2, 2021
a4bbb5a
add better hmr port detection
FredKSchott Mar 4, 2021
b7a5031
add knownEntrypoints support back
FredKSchott Mar 9, 2021
7bf6df1
update test
FredKSchott Mar 9, 2021
59560fc
revert knownEntrypoints in build, breaking change
FredKSchott Mar 9, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions esinstall/src/entrypoints.ts
@@ -1,5 +1,6 @@
import {readdirSync, existsSync, realpathSync, statSync} from 'fs';
import path from 'path';
import builtinModules from 'builtin-modules';
import validatePackageName from 'validate-npm-package-name';
import {ExportField, ExportMapEntry, PackageManifestWithExports, PackageManifest} from './types';
import {parsePackageImportSpecifier, resolveDependencyManifest} from './util';
Expand Down Expand Up @@ -184,8 +185,10 @@ export function resolveEntrypoint(
}

// if, no export map and dep points directly to a file within a package, return that reference.
if (path.extname(dep) && !validatePackageName(dep).validForNewPackages) {
return realpathSync.native(resolve.sync(dep, {basedir: cwd}));
if (builtinModules.indexOf(dep) === -1 && !validatePackageName(dep).validForNewPackages) {
return realpathSync.native(
resolve.sync(dep, {basedir: cwd, extensions: ['.js', '.mjs', '.ts', '.jsx', '.tsx']}),
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍🏻

);
}

// Otherwise, resolve directly to the dep specifier. Note that this supports both
Expand Down
41 changes: 26 additions & 15 deletions esinstall/src/index.ts
Expand Up @@ -45,6 +45,7 @@ export {
resolveEntrypoint,
explodeExportMap,
} from './entrypoints';
export {resolveDependencyManifest} from './util';
export {printStats} from './stats';

type DependencyLoc = {
Expand All @@ -70,6 +71,7 @@ const CJS_PACKAGES_TO_AUTO_DETECT = [
'react-table',
'chai/index.js',
'events/events.js',
'uuid/index.js',
];

function isImportOfPackage(importUrl: string, packageName: string) {
Expand All @@ -87,7 +89,6 @@ function resolveWebDependency(
resolveOptions: {cwd: string; packageLookupFields: string[]},
): DependencyLoc {
const loc = resolveEntrypoint(dep, resolveOptions);

return {
loc,
type: getWebDependencyType(loc),
Expand All @@ -105,11 +106,18 @@ function generateEnvObject(userEnv: EnvVarReplacements): Object {
};
}

function generateEnvReplacements(env: Object): {[key: string]: string} {
return Object.keys(env).reduce((acc, key) => {
acc[`process.env.${key}`] = JSON.stringify(env[key]);
return acc;
}, {});
function generateReplacements(env: Object): {[key: string]: string} {
return Object.keys(env).reduce(
(acc, key) => {
acc[`process.env.${key}`] = JSON.stringify(env[key]);
return acc;
},
{
// Other find & replacements:
// tslib: fights with Rollup's namespace/default handling, so just remove it.
'return (mod && mod.__esModule) ? mod : { "default": mod };': 'return mod;',
},
);
}

interface InstallOptions {
Expand All @@ -125,7 +133,7 @@ interface InstallOptions {
polyfillNode: boolean;
sourcemap?: boolean | 'inline';
external: string[];
externalEsm: string[];
externalEsm: string[] | ((imp: string) => boolean);
packageLookupFields: string[];
packageExportLookupFields: string[];
namedExports: string[];
Expand Down Expand Up @@ -167,8 +175,8 @@ function setOptionDefaults(_options: PublicInstallOptions): InstallOptions {
// TODO: Make this default to false in a v2.0 release
stats: true,
dest: 'web_modules',
external: [],
externalEsm: [],
external: [] as string[],
externalEsm: [] as string[],
polyfillNode: false,
packageLookupFields: [],
packageExportLookupFields: [],
Expand Down Expand Up @@ -308,7 +316,7 @@ ${colors.dim(
input: installEntrypoints,
context: userDefinedRollup.context,
external: (id) => external.some((packageName) => isImportOfPackage(id, packageName)),
treeshake: {moduleSideEffects: 'no-external'},
treeshake: {moduleSideEffects: true},
plugins: [
rollupPluginAlias({
entries: [
Expand Down Expand Up @@ -343,10 +351,13 @@ ${colors.dim(
namedExports: true,
}),
rollupPluginCss(),
rollupPluginReplace(generateEnvReplacements(env)),
rollupPluginReplace(generateReplacements(env)),
rollupPluginCommonjs({
extensions: ['.js', '.cjs'],
esmExternals: externalEsm,
esmExternals: (id) =>
Array.isArray(externalEsm)
? externalEsm.some((packageName) => isImportOfPackage(id, packageName))
: (externalEsm as Function)(id),
requireReturnsDefault: 'auto',
} as RollupCommonJSOptions),
rollupPluginWrapInstallTargets(!!isTreeshake, autoDetectNamedExports, installTargets, logger),
Expand All @@ -366,8 +377,7 @@ ${colors.dim(
isFatalWarningFound = true;
// Display posix-style on all environments, mainly to help with CI :)
if (warning.id) {
const fileName = path.relative(cwd, warning.id).replace(/\\/g, '/');
logger.error(`${fileName}\n ${warning.message}`);
logger.error(`${warning.id}\n ${warning.message}`);
} else {
logger.error(
`${warning.message}. See https://www.snowpack.dev/reference/common-error-details`,
Expand All @@ -381,7 +391,8 @@ ${colors.dim(
if (
warning.code === 'CIRCULAR_DEPENDENCY' ||
warning.code === 'NAMESPACE_CONFLICT' ||
warning.code === 'THIS_IS_UNDEFINED'
warning.code === 'THIS_IS_UNDEFINED' ||
warning.code === 'EMPTY_BUNDLE'
) {
logger.debug(logMessage);
} else {
Expand Down
Expand Up @@ -19,6 +19,11 @@ export function rollupPluginCatchUnresolved(): Plugin {
id: importer,
message: `Module "${id}" (Node.js built-in) is not available in the browser. Run Snowpack with --polyfill-node to fix.`,
});
} else if (id.startsWith('./') || id.startsWith('../')) {
this.warn({
id: importer,
message: `Import "${id}" could not be resolved from file.`,
});
} else {
this.warn({
id: importer,
Expand Down
5 changes: 4 additions & 1 deletion plugins/plugin-react-refresh/plugin.js
Expand Up @@ -53,7 +53,10 @@ async function transformJs(contents, id, cwd, skipTransform) {
sourceMaps: false,
configFile: false,
babelrc: false,
plugins: [require('react-refresh/babel'), require('@babel/plugin-syntax-class-properties')],
plugins: [
[require('react-refresh/babel'), {skipEnvCheck: true}],
require('@babel/plugin-syntax-class-properties'),
],
});
fastRefreshEnhancedCode = code;
}
Expand Down
35 changes: 20 additions & 15 deletions plugins/plugin-svelte/plugin.js
Expand Up @@ -13,22 +13,27 @@ module.exports = function plugin(snowpackConfig, pluginOptions = {}) {
const isDev = process.env.NODE_ENV !== 'production';
const useSourceMaps =
snowpackConfig.buildOptions.sourcemap || snowpackConfig.buildOptions.sourceMaps;
// Old Snowpack versions wouldn't build dependencies. Starting in v3.1, Snowpack's build pipeline
// is run on all files, including npm package files. The rollup plugin is no longer needed.
const needsRollupPlugin = typeof snowpackConfig.buildOptions.resolveProxyImports === 'undefined';

// Support importing Svelte files when you install dependencies.
const packageOptions = snowpackConfig.packageOptions || snowpackConfig.installOptions;
if (packageOptions.source === 'local') {
packageOptions.rollup = packageOptions.rollup || {};
packageOptions.rollup.plugins = packageOptions.rollup.plugins || [];
packageOptions.rollup.plugins.push(
svelteRollupPlugin({
include: /\.svelte$/,
compilerOptions: {dev: isDev},
// Snowpack wraps JS-imported CSS in a JS wrapper, so use
// Svelte's own first-class `emitCss: false` here.
// TODO: Remove once Snowpack adds first-class CSS import support in deps.
emitCss: false,
}),
);
if (needsRollupPlugin) {
packageOptions.rollup = packageOptions.rollup || {};
packageOptions.rollup.plugins = packageOptions.rollup.plugins || [];
packageOptions.rollup.plugins.push(
svelteRollupPlugin({
include: /\.svelte$/,
compilerOptions: {dev: isDev},
// Snowpack wraps JS-imported CSS in a JS wrapper, so use
// Svelte's own first-class `emitCss: false` here.
// TODO: Remove once Snowpack adds first-class CSS import support in deps.
emitCss: false,
}),
);
}
// Support importing sharable Svelte components.
packageOptions.packageLookupFields.push('svelte');
}
Expand Down Expand Up @@ -97,7 +102,7 @@ module.exports = function plugin(snowpackConfig, pluginOptions = {}) {
'svelte-hmr/runtime/hot-api-esm.js',
'svelte-hmr/runtime/proxy-adapter-dom.js',
],
async load({filePath, isHmrEnabled, isSSR}) {
async load({filePath, isHmrEnabled, isSSR, isPackage}) {
let codeToCompile = await fs.promises.readFile(filePath, 'utf-8');
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: utf8 is the Node encoding; utf-8 is an alias. While I think it doesn’t matter here, I think there’s one Node library (not fs) that doesn’t accept utf-8 as an encoing; only utf8, and will cause issues (if only I could remember what it was, then this comment would be more helpful!).

// PRE-PROCESS
if (preprocessOptions !== false) {
Expand All @@ -110,9 +115,9 @@ module.exports = function plugin(snowpackConfig, pluginOptions = {}) {

const finalCompileOptions = {
generate: isSSR ? 'ssr' : 'dom',
css: false,
css: isPackage ? true : false,
...compilerOptions, // Note(drew) should take precedence over generate above
dev: isDev,
dev: isHmrEnabled || isDev,
outputFilename: filePath,
filename: filePath,
};
Expand Down
1 change: 0 additions & 1 deletion plugins/plugin-svelte/test/plugin.test.js
Expand Up @@ -15,7 +15,6 @@ describe('@snowpack/plugin-svelte (mocked)', () => {
buildOptions: {sourcemap: false},
packageOptions: {
source: 'local',
rollup: {plugins: []},
packageLookupFields: [],
},
};
Expand Down
2 changes: 2 additions & 0 deletions plugins/web-test-runner-plugin/plugin.js
Expand Up @@ -27,6 +27,8 @@ To Resolve:
packageOptions: {external: ['/__web-dev-server__web-socket.js']},
devOptions: {open: 'none', output: 'stream', hmr: false},
});
// npm packages should be installed/prepared ahead of time.
console.log('[snowpack] starting server...');
fileWatcher.add(Object.keys(config.mount));
server = await snowpack.startServer({
config,
Expand Down
27 changes: 27 additions & 0 deletions snowpack/LICENSE
Expand Up @@ -19,3 +19,30 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


"""

This license applies to parts of the src/dev.ts file originating from the
https://github.com/lukejacksonn/servor repository:

MIT License
Copyright (c) 2019 Luke Jackson

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
6 changes: 3 additions & 3 deletions snowpack/package.json
Expand Up @@ -45,19 +45,19 @@
"vendor"
],
"dependencies": {
"cli-spinners": "^2.5.0",
"default-browser-id": "^2.0.0",
"esbuild": "^0.8.7",
"open": "^7.0.4",
"rollup": "^2.34.0",
"resolve": "^1.20.0"
"resolve": "^1.20.0",
"rollup": "^2.34.0"
},
"optionalDependencies": {
"fsevents": "^2.2.0"
},
"devDependencies": {
"@types/cheerio": "0.22.22",
"bufferutil": "^4.0.2",
"cacache": "^15.0.0",
Copy link
Collaborator

Choose a reason for hiding this comment

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

🎉

"cachedir": "^2.3.0",
"cheerio": "1.0.0-rc.3",
"chokidar": "^3.4.0",
Expand Down
24 changes: 11 additions & 13 deletions snowpack/src/build/build-import-proxy.ts
Expand Up @@ -6,8 +6,8 @@ import {SnowpackConfig} from '../types';
import {appendHtmlToHead, hasExtension, HMR_CLIENT_CODE, HMR_OVERLAY_CODE} from '../util';
import {generateSRI} from './import-sri';

const SRI_CLIENT_HMR_SNOWPACK = generateSRI(Buffer.from(HMR_CLIENT_CODE));
const SRI_ERROR_HMR_SNOWPACK = generateSRI(Buffer.from(HMR_OVERLAY_CODE));
export const SRI_CLIENT_HMR_SNOWPACK = generateSRI(Buffer.from(HMR_CLIENT_CODE));
export const SRI_ERROR_HMR_SNOWPACK = generateSRI(Buffer.from(HMR_OVERLAY_CODE));

const importMetaRegex = /import\s*\.\s*meta/;

Expand Down Expand Up @@ -235,18 +235,16 @@ export async function wrapImportProxy({
hmr: boolean;
config: SnowpackConfig;
}) {
if (typeof code === 'string') {
if (hasExtension(url, '.json')) {
return generateJsonImportProxy({code, hmr, config});
}
if (hasExtension(url, '.json')) {
return generateJsonImportProxy({code: code.toString(), hmr, config});
}

if (hasExtension(url, '.css')) {
// if proxying a CSS file, remove its source map (the path no longer applies)
const sanitized = code.replace(/\/\*#\s*sourceMappingURL=[^/]+\//gm, '');
return hasExtension(url, '.module.css')
? generateCssModuleImportProxy({url, code: sanitized, hmr, config})
: generateCssImportProxy({code: sanitized, hmr, config});
}
if (hasExtension(url, '.css')) {
// if proxying a CSS file, remove its source map (the path no longer applies)
const sanitized = code.toString().replace(/\/\*#\s*sourceMappingURL=[^/]+\//gm, '');
return hasExtension(url, '.module.css')
? generateCssModuleImportProxy({url, code: sanitized, hmr, config})
: generateCssImportProxy({code: sanitized, hmr, config});
}

return generateDefaultImportProxy(url);
Expand Down