diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 70bd73ace03f..1843f327ecd8 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -90,7 +90,7 @@ "templating" ], "scripts": { - "build": "rollup -c && node scripts/build.js", + "build": "rollup -c && node scripts/build.js && node scripts/check-treeshakeability.js", "watch": "rollup -cw", "check": "tsc && cd ./tests/types && tsc", "check:watch": "tsc --watch", @@ -103,6 +103,7 @@ "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-virtual": "^3.0.2", "@types/aria-query": "^5.0.3", "@types/estree": "^1.0.5", "dts-buddy": "^0.4.0", diff --git a/packages/svelte/scripts/check-treeshakeability.js b/packages/svelte/scripts/check-treeshakeability.js new file mode 100644 index 000000000000..503501292c41 --- /dev/null +++ b/packages/svelte/scripts/check-treeshakeability.js @@ -0,0 +1,62 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { rollup } from 'rollup'; +import virtual from '@rollup/plugin-virtual'; + +const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); + +let failed = false; + +// eslint-disable-next-line no-console +console.group('checking treeshakeability'); + +for (const key in pkg.exports) { + // special cases + if (key === './compiler') continue; + if (key === './internal/disclose-version') continue; + + for (const type of ['browser', 'default']) { + if (!pkg.exports[key][type]) continue; + + const subpackage = path.join(pkg.name, key); + + const resolved = path.resolve(pkg.exports[key][type]); + + const bundle = await rollup({ + input: '__entry__', + plugins: [ + virtual({ + __entry__: `import ${JSON.stringify(resolved)}` + }) + ], + onwarn: (warning, handle) => { + // if (warning.code !== 'EMPTY_BUNDLE') handle(warning); + } + }); + + const { output } = await bundle.generate({}); + + if (output.length > 1) { + throw new Error('errr what'); + } + + const code = output[0].code.replace(/import\s+([^'"]+from\s+)?(['"])[^'"]+\2\s*;?/, ''); + if (code.trim()) { + // eslint-disable-next-line no-console + console.error(code); + // eslint-disable-next-line no-console + console.error(`❌ ${subpackage} (${type})`); + failed = true; + } else { + // eslint-disable-next-line no-console + console.error(`✅ ${subpackage} (${type})`); + } + } +} + +// eslint-disable-next-line no-console +console.groupEnd(); + +if (failed) { + process.exit(1); +} diff --git a/packages/svelte/src/internal/server/index.js b/packages/svelte/src/internal/server/index.js index 080cc13d72fb..7ba8408090b8 100644 --- a/packages/svelte/src/internal/server/index.js +++ b/packages/svelte/src/internal/server/index.js @@ -32,7 +32,7 @@ const INVALID_ATTR_NAME_CHAR_REGEX = /[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u; // This is duplicated from the compiler, but we need it at runtime too. -const DOMBooleans = [ +export const DOMBooleanAttributes = [ 'allowfullscreen', 'async', 'autofocus', @@ -59,9 +59,6 @@ const DOMBooleans = [ 'selected' ]; -/** @type {Set} */ -export const DOMBooleanAttributes = new Set(DOMBooleans); - export const VoidElements = new Set([ 'area', 'base', @@ -280,7 +277,7 @@ export function spread_attributes(attrs, class_hash, additional) { for (name in merged_attrs) { if (INVALID_ATTR_NAME_CHAR_REGEX.test(name)) continue; - const is_boolean = DOMBooleanAttributes.has(name); + const is_boolean = DOMBooleanAttributes.includes(name); attr_str += attr(name, merged_attrs[name], is_boolean); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cb0e47baa767..1dffc51f176b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,6 +108,9 @@ importers: '@rollup/plugin-terser': specifier: ^0.4.4 version: 0.4.4(rollup@4.3.0) + '@rollup/plugin-virtual': + specifier: ^3.0.2 + version: 3.0.2(rollup@4.3.0) '@types/aria-query': specifier: ^5.0.3 version: 5.0.4 @@ -1962,6 +1965,18 @@ packages: terser: 5.24.0 dev: true + /@rollup/plugin-virtual@3.0.2(rollup@4.3.0): + resolution: {integrity: sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + rollup: 4.3.0 + dev: true + /@rollup/pluginutils@4.2.1: resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} engines: {node: '>= 8.0.0'}