@quilted/rollup 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,28 +5,30 @@ import { getNodePlugins, removeBuildFiles } from './shared/rollup.mjs';
5
5
  import { loadPackageJSON } from './shared/package-json.mjs';
6
6
 
7
7
  async function quiltPackageESModules({
8
- root: rootPath = process.cwd()
8
+ root: rootPath = process.cwd(),
9
+ graphql = true
9
10
  } = {}) {
10
11
  const root = typeof rootPath === 'string' ? rootPath : fileURLToPath(rootPath);
11
12
  const outputDirectory = path.join(root, 'build/esm');
12
13
  const [{
13
14
  sourceCode
14
15
  }, nodePlugins, packageJSON] = await Promise.all([import('./features/source-code.mjs'), getNodePlugins(), loadPackageJSON(root)]);
15
- const [entries] = await Promise.all([sourceEntriesForPackage(root, packageJSON)]);
16
- let sourceRoot = root;
17
- const sourceEntryFiles = Object.values(entries);
18
- for (const entry of sourceEntryFiles) {
19
- if (!entry.startsWith(root)) continue;
20
- sourceRoot = path.resolve(root, path.relative(root, entry).split(path.sep)[0] ?? '.');
21
- break;
22
- }
16
+ const source = await sourceForPackage(root, packageJSON);
23
17
  const plugins = [...nodePlugins, sourceCode({
24
18
  mode: 'production'
25
19
  }), removeBuildFiles(['build/esm'], {
26
20
  root
27
21
  })];
22
+ if (graphql) {
23
+ const {
24
+ graphql
25
+ } = await import('./features/graphql.mjs');
26
+ plugins.push(graphql({
27
+ manifest: false
28
+ }));
29
+ }
28
30
  return {
29
- input: sourceEntryFiles,
31
+ input: source.files,
30
32
  plugins,
31
33
  onwarn(warning, defaultWarn) {
32
34
  // Removes annoying warnings for React-focused libraries that
@@ -38,7 +40,7 @@ async function quiltPackageESModules({
38
40
  },
39
41
  output: {
40
42
  preserveModules: true,
41
- preserveModulesRoot: sourceRoot,
43
+ preserveModulesRoot: source.root,
42
44
  format: 'esm',
43
45
  dir: outputDirectory,
44
46
  entryFileNames: `[name].mjs`,
@@ -46,6 +48,65 @@ async function quiltPackageESModules({
46
48
  }
47
49
  };
48
50
  }
51
+ async function quiltPackageESNext({
52
+ root: rootPath = process.cwd(),
53
+ graphql = true
54
+ } = {}) {
55
+ const root = typeof rootPath === 'string' ? rootPath : fileURLToPath(rootPath);
56
+ const outputDirectory = path.join(root, 'build/esnext');
57
+ const [{
58
+ sourceCode
59
+ }, nodePlugins, packageJSON] = await Promise.all([import('./features/source-code.mjs'), getNodePlugins(), loadPackageJSON(root)]);
60
+ const source = await sourceForPackage(root, packageJSON);
61
+ const plugins = [...nodePlugins, sourceCode({
62
+ mode: 'production',
63
+ babel: false
64
+ }), removeBuildFiles(['build/esnext'], {
65
+ root
66
+ })];
67
+ if (graphql) {
68
+ const {
69
+ graphql
70
+ } = await import('./features/graphql.mjs');
71
+ plugins.push(graphql({
72
+ manifest: false
73
+ }));
74
+ }
75
+ return {
76
+ input: source.files,
77
+ plugins,
78
+ onwarn(warning, defaultWarn) {
79
+ // Removes annoying warnings for React-focused libraries that
80
+ // include 'use client' directives.
81
+ if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && /['"]use client['"]/.test(warning.message)) {
82
+ return;
83
+ }
84
+ defaultWarn(warning);
85
+ },
86
+ output: {
87
+ preserveModules: true,
88
+ preserveModulesRoot: source.root,
89
+ format: 'esm',
90
+ dir: outputDirectory,
91
+ entryFileNames: `[name].esnext`,
92
+ assetFileNames: `[name].[ext]`
93
+ }
94
+ };
95
+ }
96
+ async function sourceForPackage(root, packageJSON) {
97
+ const [entries] = await Promise.all([sourceEntriesForPackage(root, packageJSON)]);
98
+ let sourceRoot = root;
99
+ const sourceEntryFiles = Object.values(entries);
100
+ for (const entry of sourceEntryFiles) {
101
+ if (!entry.startsWith(root)) continue;
102
+ sourceRoot = path.resolve(root, path.relative(root, entry).split(path.sep)[0] ?? '.');
103
+ break;
104
+ }
105
+ return {
106
+ root: sourceRoot,
107
+ files: sourceEntryFiles
108
+ };
109
+ }
49
110
  async function sourceEntriesForPackage(root, packageJSON) {
50
111
  const {
51
112
  main,
@@ -84,4 +145,4 @@ async function resolveTargetFileAsSource(file, root) {
84
145
  return sourceFile;
85
146
  }
86
147
 
87
- export { quiltPackageESModules };
148
+ export { quiltPackageESModules, quiltPackageESNext };
@@ -37,8 +37,6 @@ async function quiltAppBrowser({
37
37
  const targetFilenamePart = normalizedTargetName ? `.${normalizedTargetName}` : '';
38
38
  const [{
39
39
  visualizer
40
- }, {
41
- assetManifest
42
40
  }, {
43
41
  sourceCode
44
42
  }, {
@@ -46,11 +44,12 @@ async function quiltAppBrowser({
46
44
  }, {
47
45
  css
48
46
  }, {
47
+ assetManifest,
49
48
  rawAssets,
50
49
  staticAssets
51
50
  }, {
52
51
  systemJS
53
- }, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), import('@quilted/assets/rollup'), import('./features/source-code.esnext'), import('./features/typescript.esnext'), import('./features/css.esnext'), import('./features/assets.esnext'), import('./features/system-js.esnext'), getNodePlugins()]);
52
+ }, nodePlugins] = await Promise.all([import('rollup-plugin-visualizer'), import('./features/source-code.esnext'), import('./features/typescript.esnext'), import('./features/css.esnext'), import('./features/assets.esnext'), import('./features/system-js.esnext'), getNodePlugins()]);
54
53
  const plugins = [...nodePlugins, systemJS({
55
54
  minify
56
55
  }), sourceCode({
@@ -119,13 +118,11 @@ async function quiltAppBrowser({
119
118
  browserTarget: targets.name
120
119
  } : undefined;
121
120
  const id = targets.name ? targets.name : undefined;
122
- plugins.push(
123
- // @ts-expect-error The plugin still depends on Rollup 3
124
- assetManifest({
121
+ plugins.push(assetManifest({
125
122
  id,
126
123
  cacheKey,
127
- baseUrl: baseURL,
128
- path: path.resolve(`build/manifests/assets${targetFilenamePart}.json`),
124
+ baseURL,
125
+ file: path.resolve(`build/manifests/assets${targetFilenamePart}.json`),
129
126
  priority: assets?.priority
130
127
  }), visualizer({
131
128
  template: 'treemap',
@@ -1,8 +1,116 @@
1
1
  import * as path from 'node:path';
2
- import { readFile } from 'node:fs/promises';
2
+ import * as fs from 'node:fs/promises';
3
3
  import { createHash } from 'node:crypto';
4
4
  import * as mime from 'mrmime';
5
5
 
6
+ function assetManifest(manifestOptions) {
7
+ return {
8
+ name: '@quilted/asset-manifest',
9
+ async generateBundle(options, bundle) {
10
+ await writeManifestForBundle.call(this, bundle, manifestOptions, options);
11
+ }
12
+ };
13
+ }
14
+ async function writeManifestForBundle(bundle, {
15
+ id,
16
+ file,
17
+ baseURL,
18
+ cacheKey,
19
+ priority
20
+ }, {
21
+ format
22
+ }) {
23
+ const outputs = Object.values(bundle);
24
+ const entries = outputs.filter(output => output.type === 'chunk' && output.isEntry);
25
+ if (entries.length === 0) {
26
+ throw new Error(`Could not find any entries in your rollup bundle...`);
27
+ }
28
+
29
+ // We assume the first entry is the "main" one. There can be
30
+ // more than one because each worker script is also listed as an
31
+ // entry (though, from a separate build).
32
+ const entryChunk = entries[0];
33
+ const dependencyMap = new Map();
34
+ for (const output of outputs) {
35
+ if (output.type !== 'chunk') continue;
36
+ dependencyMap.set(output.fileName, output.imports);
37
+ }
38
+ const assets = [];
39
+ const assetIdMap = new Map();
40
+ function getAssetId(file) {
41
+ let id = assetIdMap.get(file);
42
+ if (id == null) {
43
+ assets.push(`${baseURL}${file}`);
44
+ id = assets.length - 1;
45
+ assetIdMap.set(file, id);
46
+ }
47
+ return id;
48
+ }
49
+ const manifest = {
50
+ id,
51
+ priority,
52
+ cacheKey,
53
+ assets,
54
+ attributes: format === 'es' ? {
55
+ scripts: {
56
+ type: 'module'
57
+ }
58
+ } : undefined,
59
+ entries: {
60
+ default: createAssetsEntry([...entryChunk.imports, entryChunk.fileName], {
61
+ dependencyMap,
62
+ getAssetId
63
+ })
64
+ },
65
+ modules: {}
66
+ };
67
+ for (const output of outputs) {
68
+ if (output.type !== 'chunk') continue;
69
+ const originalModuleId = output.facadeModuleId ?? output.moduleIds[output.moduleIds.length - 1];
70
+ if (originalModuleId == null) continue;
71
+
72
+ // This metadata is added by the rollup plugin for @quilted/async
73
+ const moduleId = this.getModuleInfo(originalModuleId)?.meta.quilt?.moduleId;
74
+ if (moduleId == null) continue;
75
+ manifest.modules[moduleId] = createAssetsEntry([...output.imports, output.fileName], {
76
+ dependencyMap,
77
+ getAssetId
78
+ });
79
+ }
80
+ await fs.mkdir(path.dirname(file), {
81
+ recursive: true
82
+ });
83
+ await fs.writeFile(file, JSON.stringify(manifest, null, 2));
84
+ }
85
+ function createAssetsEntry(files, {
86
+ dependencyMap,
87
+ getAssetId
88
+ }) {
89
+ const styles = [];
90
+ const scripts = [];
91
+ const allFiles = new Set();
92
+ const addFile = file => {
93
+ if (allFiles.has(file)) return;
94
+ allFiles.add(file);
95
+ for (const dependency of dependencyMap.get(file) ?? []) {
96
+ addFile(dependency);
97
+ }
98
+ };
99
+ for (const file of files) {
100
+ addFile(file);
101
+ }
102
+ for (const file of allFiles) {
103
+ if (file.endsWith('.css')) {
104
+ styles.push(getAssetId(file));
105
+ } else {
106
+ scripts.push(getAssetId(file));
107
+ }
108
+ }
109
+ return {
110
+ scripts,
111
+ styles
112
+ };
113
+ }
6
114
  const QUERY_PATTERN = /\?.*$/s;
7
115
  const HASH_PATTERN = /#.*$/s;
8
116
  const RAW_PATTERN = /(\?|&)raw(?:&|$)/;
@@ -26,7 +134,7 @@ function rawAssets() {
26
134
  }
27
135
  const moduleId = cleanModuleIdentifier(id);
28
136
  this.addWatchFile(moduleId);
29
- const file = await readFile(moduleId, {
137
+ const file = await fs.readFile(moduleId, {
30
138
  encoding: 'utf-8'
31
139
  });
32
140
  return `export default ${JSON.stringify(file)}`;
@@ -53,7 +161,7 @@ function staticAssets({
53
161
  return cached;
54
162
  }
55
163
  const file = cleanModuleIdentifier(id);
56
- const content = await readFile(file);
164
+ const content = await fs.readFile(file);
57
165
  let url;
58
166
  if (!file.endsWith('.svg') && content.length < inlineLimit) {
59
167
  // base64 inlined as a string
@@ -104,4 +212,4 @@ function cleanModuleIdentifier(url) {
104
212
  return url.replace(HASH_PATTERN, '').replace(QUERY_PATTERN, '');
105
213
  }
106
214
 
107
- export { rawAssets, staticAssets };
215
+ export { assetManifest, rawAssets, staticAssets };
@@ -1,11 +1,22 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import babel from '@rollup/plugin-babel';
3
+ import esbuild from 'rollup-plugin-esbuild';
3
4
 
4
5
  const require = createRequire(import.meta.url);
5
6
  function sourceCode({
6
7
  mode,
7
- targets
8
+ targets,
9
+ babel: useBabel = true
8
10
  }) {
11
+ if (!useBabel) {
12
+ return esbuild({
13
+ // Support very modern features
14
+ target: 'es2022',
15
+ jsx: 'automatic',
16
+ jsxImportSource: 'react',
17
+ exclude: 'node_modules/**'
18
+ });
19
+ }
9
20
  return babel({
10
21
  envName: mode,
11
22
  configFile: false,
@@ -1,2 +1,2 @@
1
1
  export { quiltAppBrowser, quiltAppServer } from './app.esnext';
2
- export { quiltPackageESModules } from './package.esnext';
2
+ export { quiltPackageESModules, quiltPackageESNext } from './package.esnext';
@@ -5,28 +5,30 @@ import { getNodePlugins, removeBuildFiles } from './shared/rollup.esnext';
5
5
  import { loadPackageJSON } from './shared/package-json.esnext';
6
6
 
7
7
  async function quiltPackageESModules({
8
- root: rootPath = process.cwd()
8
+ root: rootPath = process.cwd(),
9
+ graphql = true
9
10
  } = {}) {
10
11
  const root = typeof rootPath === 'string' ? rootPath : fileURLToPath(rootPath);
11
12
  const outputDirectory = path.join(root, 'build/esm');
12
13
  const [{
13
14
  sourceCode
14
15
  }, nodePlugins, packageJSON] = await Promise.all([import('./features/source-code.esnext'), getNodePlugins(), loadPackageJSON(root)]);
15
- const [entries] = await Promise.all([sourceEntriesForPackage(root, packageJSON)]);
16
- let sourceRoot = root;
17
- const sourceEntryFiles = Object.values(entries);
18
- for (const entry of sourceEntryFiles) {
19
- if (!entry.startsWith(root)) continue;
20
- sourceRoot = path.resolve(root, path.relative(root, entry).split(path.sep)[0] ?? '.');
21
- break;
22
- }
16
+ const source = await sourceForPackage(root, packageJSON);
23
17
  const plugins = [...nodePlugins, sourceCode({
24
18
  mode: 'production'
25
19
  }), removeBuildFiles(['build/esm'], {
26
20
  root
27
21
  })];
22
+ if (graphql) {
23
+ const {
24
+ graphql
25
+ } = await import('./features/graphql.esnext');
26
+ plugins.push(graphql({
27
+ manifest: false
28
+ }));
29
+ }
28
30
  return {
29
- input: sourceEntryFiles,
31
+ input: source.files,
30
32
  plugins,
31
33
  onwarn(warning, defaultWarn) {
32
34
  // Removes annoying warnings for React-focused libraries that
@@ -38,7 +40,7 @@ async function quiltPackageESModules({
38
40
  },
39
41
  output: {
40
42
  preserveModules: true,
41
- preserveModulesRoot: sourceRoot,
43
+ preserveModulesRoot: source.root,
42
44
  format: 'esm',
43
45
  dir: outputDirectory,
44
46
  entryFileNames: `[name].mjs`,
@@ -46,6 +48,65 @@ async function quiltPackageESModules({
46
48
  }
47
49
  };
48
50
  }
51
+ async function quiltPackageESNext({
52
+ root: rootPath = process.cwd(),
53
+ graphql = true
54
+ } = {}) {
55
+ const root = typeof rootPath === 'string' ? rootPath : fileURLToPath(rootPath);
56
+ const outputDirectory = path.join(root, 'build/esnext');
57
+ const [{
58
+ sourceCode
59
+ }, nodePlugins, packageJSON] = await Promise.all([import('./features/source-code.esnext'), getNodePlugins(), loadPackageJSON(root)]);
60
+ const source = await sourceForPackage(root, packageJSON);
61
+ const plugins = [...nodePlugins, sourceCode({
62
+ mode: 'production',
63
+ babel: false
64
+ }), removeBuildFiles(['build/esnext'], {
65
+ root
66
+ })];
67
+ if (graphql) {
68
+ const {
69
+ graphql
70
+ } = await import('./features/graphql.esnext');
71
+ plugins.push(graphql({
72
+ manifest: false
73
+ }));
74
+ }
75
+ return {
76
+ input: source.files,
77
+ plugins,
78
+ onwarn(warning, defaultWarn) {
79
+ // Removes annoying warnings for React-focused libraries that
80
+ // include 'use client' directives.
81
+ if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && /['"]use client['"]/.test(warning.message)) {
82
+ return;
83
+ }
84
+ defaultWarn(warning);
85
+ },
86
+ output: {
87
+ preserveModules: true,
88
+ preserveModulesRoot: source.root,
89
+ format: 'esm',
90
+ dir: outputDirectory,
91
+ entryFileNames: `[name].esnext`,
92
+ assetFileNames: `[name].[ext]`
93
+ }
94
+ };
95
+ }
96
+ async function sourceForPackage(root, packageJSON) {
97
+ const [entries] = await Promise.all([sourceEntriesForPackage(root, packageJSON)]);
98
+ let sourceRoot = root;
99
+ const sourceEntryFiles = Object.values(entries);
100
+ for (const entry of sourceEntryFiles) {
101
+ if (!entry.startsWith(root)) continue;
102
+ sourceRoot = path.resolve(root, path.relative(root, entry).split(path.sep)[0] ?? '.');
103
+ break;
104
+ }
105
+ return {
106
+ root: sourceRoot,
107
+ files: sourceEntryFiles
108
+ };
109
+ }
49
110
  async function sourceEntriesForPackage(root, packageJSON) {
50
111
  const {
51
112
  main,
@@ -84,4 +145,4 @@ async function resolveTargetFileAsSource(file, root) {
84
145
  return sourceFile;
85
146
  }
86
147
 
87
- export { quiltPackageESModules };
148
+ export { quiltPackageESModules, quiltPackageESNext };