@quilted/rollup 0.1.4 → 0.1.5
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.
- package/CHANGELOG.md +8 -0
- package/build/cjs/app.cjs +144 -142
- package/build/cjs/features/assets.cjs +130 -0
- package/build/cjs/{env.cjs → features/env.cjs} +4 -4
- package/build/cjs/{request-router.cjs → features/request-router.cjs} +3 -3
- package/build/cjs/{shared → features}/source-code.cjs +1 -1
- package/build/cjs/features/system-js.cjs +35 -0
- package/build/cjs/index.cjs +0 -7
- package/build/cjs/shared/rollup.cjs +0 -4
- package/build/esm/app.mjs +146 -144
- package/build/esm/features/assets.mjs +107 -0
- package/build/esm/{env.mjs → features/env.mjs} +4 -4
- package/build/esm/{request-router.mjs → features/request-router.mjs} +3 -3
- package/build/esm/features/system-js.mjs +33 -0
- package/build/esm/index.mjs +1 -3
- package/build/esm/shared/rollup.mjs +1 -4
- package/build/esnext/app.esnext +146 -144
- package/build/esnext/features/assets.esnext +107 -0
- package/build/esnext/{env.esnext → features/env.esnext} +4 -4
- package/build/esnext/{request-router.esnext → features/request-router.esnext} +3 -3
- package/build/esnext/features/system-js.esnext +33 -0
- package/build/esnext/index.esnext +1 -3
- package/build/esnext/shared/rollup.esnext +1 -4
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/app.d.ts +32 -144
- package/build/typescript/app.d.ts.map +1 -1
- package/build/typescript/features/assets.d.ts +13 -0
- package/build/typescript/features/assets.d.ts.map +1 -0
- package/build/typescript/features/css.d.ts +16 -0
- package/build/typescript/features/css.d.ts.map +1 -0
- package/build/typescript/features/env.d.ts +57 -0
- package/build/typescript/features/env.d.ts.map +1 -0
- package/build/typescript/features/graphql/transform.d.ts +17 -0
- package/build/typescript/features/graphql/transform.d.ts.map +1 -0
- package/build/typescript/features/graphql.d.ts +6 -0
- package/build/typescript/features/graphql.d.ts.map +1 -0
- package/build/typescript/features/request-router.d.ts +15 -0
- package/build/typescript/features/request-router.d.ts.map +1 -0
- package/build/typescript/features/source-code.d.ts +5 -0
- package/build/typescript/features/source-code.d.ts.map +1 -0
- package/build/typescript/features/system-js.d.ts +7 -0
- package/build/typescript/features/system-js.d.ts.map +1 -0
- package/build/typescript/index.d.ts +1 -3
- package/build/typescript/index.d.ts.map +1 -1
- package/package.json +5 -2
- package/source/app.ts +168 -124
- package/source/features/assets.ts +183 -0
- package/source/features/css.ts +91 -0
- package/source/{env.ts → features/env.ts} +4 -4
- package/source/{request-router.ts → features/request-router.ts} +3 -3
- package/source/features/system-js.ts +36 -0
- package/source/index.ts +0 -5
- /package/build/cjs/{graphql → features/graphql}/transform.cjs +0 -0
- /package/build/cjs/{graphql.cjs → features/graphql.cjs} +0 -0
- /package/build/esm/{graphql → features/graphql}/transform.mjs +0 -0
- /package/build/esm/{graphql.mjs → features/graphql.mjs} +0 -0
- /package/build/esm/{shared → features}/source-code.mjs +0 -0
- /package/build/esnext/{graphql → features/graphql}/transform.esnext +0 -0
- /package/build/esnext/{graphql.esnext → features/graphql.esnext} +0 -0
- /package/build/esnext/{shared → features}/source-code.esnext +0 -0
- /package/source/{graphql → features/graphql}/transform.ts +0 -0
- /package/source/{graphql.ts → features/graphql.ts} +0 -0
- /package/source/{shared → features}/source-code.ts +0 -0
package/source/app.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type {Plugin, RollupOptions, GetManualChunk} from 'rollup';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
MAGIC_MODULE_ENTRY,
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
MAGIC_MODULE_BROWSER_ASSETS,
|
|
9
9
|
MAGIC_MODULE_REQUEST_ROUTER,
|
|
10
10
|
} from './constants.ts';
|
|
11
|
-
import type {MagicModuleEnvOptions} from './env.ts';
|
|
11
|
+
import type {MagicModuleEnvOptions} from './features/env.ts';
|
|
12
12
|
|
|
13
13
|
import {multiline} from './shared/strings.ts';
|
|
14
|
-
import {getNodePlugins
|
|
14
|
+
import {getNodePlugins} from './shared/rollup.ts';
|
|
15
15
|
import {createMagicModulePlugin} from './shared/magic-module.ts';
|
|
16
16
|
|
|
17
17
|
export interface AppOptions {
|
|
@@ -22,8 +22,9 @@ export interface AppOptions {
|
|
|
22
22
|
* to create browser and server-side entries for your project.
|
|
23
23
|
*
|
|
24
24
|
* If you only want to use a custom entry module for the browser build, use the
|
|
25
|
-
* `
|
|
26
|
-
* for the server-side build, use the `server.entry` option
|
|
25
|
+
* `entry` option of the `quiltAppBrowser()` instead. If you only want to use a
|
|
26
|
+
* custom entry module for the server-side build, use the `server.entry` option
|
|
27
|
+
* instead.
|
|
27
28
|
*
|
|
28
29
|
* @example './App.tsx'
|
|
29
30
|
*/
|
|
@@ -46,7 +47,18 @@ export interface AppOptions {
|
|
|
46
47
|
|
|
47
48
|
export interface AppBrowserOptions extends AppOptions {
|
|
48
49
|
/**
|
|
49
|
-
*
|
|
50
|
+
* The entry module for this browser. This should be an absolute path, or relative
|
|
51
|
+
* path from the root directory containing your project. This entry should be the
|
|
52
|
+
* browser entrypoint.
|
|
53
|
+
*
|
|
54
|
+
* @example './browser.tsx'
|
|
55
|
+
* @default 'quilt:module/entry'
|
|
56
|
+
*/
|
|
57
|
+
entry?: string;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Customizes the magic `quilt:module/entry` module, which can be used as a "magic"
|
|
61
|
+
* entry for your application.
|
|
50
62
|
*/
|
|
51
63
|
module?: AppBrowserModuleOptions;
|
|
52
64
|
|
|
@@ -81,8 +93,9 @@ export interface AppBrowserAssetsOptions {
|
|
|
81
93
|
minify?: boolean;
|
|
82
94
|
}
|
|
83
95
|
|
|
84
|
-
export function quiltAppBrowser({
|
|
96
|
+
export async function quiltAppBrowser({
|
|
85
97
|
app,
|
|
98
|
+
entry = MAGIC_MODULE_ENTRY,
|
|
86
99
|
env,
|
|
87
100
|
assets,
|
|
88
101
|
module,
|
|
@@ -90,78 +103,82 @@ export function quiltAppBrowser({
|
|
|
90
103
|
}: AppBrowserOptions = {}) {
|
|
91
104
|
const mode =
|
|
92
105
|
(typeof env === 'object' ? env?.mode : undefined) ?? 'production';
|
|
106
|
+
const minify = assets?.minify ?? true;
|
|
107
|
+
|
|
108
|
+
const [
|
|
109
|
+
{visualizer},
|
|
110
|
+
{sourceCode},
|
|
111
|
+
{rawAssets, staticAssets},
|
|
112
|
+
{systemJS},
|
|
113
|
+
nodePlugins,
|
|
114
|
+
] = await Promise.all([
|
|
115
|
+
import('rollup-plugin-visualizer'),
|
|
116
|
+
import('./features/source-code.ts'),
|
|
117
|
+
import('./features/assets.ts'),
|
|
118
|
+
import('./features/system-js.ts'),
|
|
119
|
+
getNodePlugins(),
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
const plugins: Plugin[] = [
|
|
123
|
+
...nodePlugins,
|
|
124
|
+
systemJS(),
|
|
125
|
+
sourceCode({mode}),
|
|
126
|
+
rawAssets(),
|
|
127
|
+
staticAssets(),
|
|
128
|
+
];
|
|
129
|
+
|
|
130
|
+
if (env) {
|
|
131
|
+
const {magicModuleEnv, replaceProcessEnv} = await import(
|
|
132
|
+
'./features/env.ts'
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
if (typeof env === 'boolean') {
|
|
136
|
+
plugins.push(replaceProcessEnv({mode}));
|
|
137
|
+
plugins.push(magicModuleEnv({mode}));
|
|
138
|
+
} else {
|
|
139
|
+
plugins.push(replaceProcessEnv({mode}));
|
|
140
|
+
plugins.push(magicModuleEnv({mode}));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
93
143
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const newPlugins = rollupPluginsToArray(originalOptions.plugins);
|
|
98
|
-
const newOptions = {...originalOptions, plugins: newPlugins};
|
|
99
|
-
|
|
100
|
-
const [{visualizer}, {sourceCode}, nodePlugins] = await Promise.all([
|
|
101
|
-
import('rollup-plugin-visualizer'),
|
|
102
|
-
import('./shared/source-code.ts'),
|
|
103
|
-
getNodePlugins(),
|
|
104
|
-
]);
|
|
105
|
-
|
|
106
|
-
newPlugins.push(...nodePlugins);
|
|
107
|
-
newPlugins.push(sourceCode({mode}));
|
|
108
|
-
|
|
109
|
-
if (env) {
|
|
110
|
-
const {magicModuleEnv, replaceProcessEnv} = await import('./env.ts');
|
|
111
|
-
|
|
112
|
-
if (typeof env === 'boolean') {
|
|
113
|
-
newPlugins.push(replaceProcessEnv({mode: 'production'}));
|
|
114
|
-
newPlugins.push(magicModuleEnv({mode: 'production'}));
|
|
115
|
-
} else {
|
|
116
|
-
newPlugins.push(replaceProcessEnv({mode: env.mode ?? 'production'}));
|
|
117
|
-
newPlugins.push(magicModuleEnv({mode: 'production', ...env}));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (app) {
|
|
122
|
-
newPlugins.push(magicModuleAppComponent({entry: app}));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
newPlugins.push(magicModuleAppBrowserEntry(module));
|
|
144
|
+
if (app) {
|
|
145
|
+
plugins.push(magicModuleAppComponent({entry: app}));
|
|
146
|
+
}
|
|
126
147
|
|
|
127
|
-
|
|
128
|
-
const {graphql} = await import('./graphql.ts');
|
|
129
|
-
newPlugins.push(
|
|
130
|
-
graphql({manifest: path.resolve(`manifests/graphql.json`)}),
|
|
131
|
-
);
|
|
132
|
-
}
|
|
148
|
+
plugins.push(magicModuleAppBrowserEntry(module));
|
|
133
149
|
|
|
134
|
-
|
|
150
|
+
if (graphql) {
|
|
151
|
+
const {graphql} = await import('./features/graphql.ts');
|
|
152
|
+
plugins.push(graphql({manifest: path.resolve(`manifests/graphql.json`)}));
|
|
153
|
+
}
|
|
135
154
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
155
|
+
if (minify) {
|
|
156
|
+
const {minify} = await import('rollup-plugin-esbuild');
|
|
157
|
+
plugins.push(minify());
|
|
158
|
+
}
|
|
140
159
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
160
|
+
plugins.push(
|
|
161
|
+
visualizer({
|
|
162
|
+
template: 'treemap',
|
|
163
|
+
open: false,
|
|
164
|
+
brotliSize: true,
|
|
165
|
+
filename: path.resolve(`reports/bundle-visualizer.html`),
|
|
166
|
+
}),
|
|
167
|
+
);
|
|
149
168
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
manualChunks: createManualChunksSorter(),
|
|
162
|
-
};
|
|
169
|
+
return {
|
|
170
|
+
input: entry,
|
|
171
|
+
plugins,
|
|
172
|
+
output: {
|
|
173
|
+
// format: isESM ? 'esm' : 'systemjs',
|
|
174
|
+
format: 'esm',
|
|
175
|
+
dir: path.resolve(`build/assets`),
|
|
176
|
+
entryFileNames: `app.[hash].js`,
|
|
177
|
+
assetFileNames: `[name].[hash].[ext]`,
|
|
178
|
+
chunkFileNames: `[name].[hash].js`,
|
|
179
|
+
manualChunks: createManualChunksSorter(),
|
|
163
180
|
},
|
|
164
|
-
} satisfies
|
|
181
|
+
} satisfies RollupOptions;
|
|
165
182
|
}
|
|
166
183
|
|
|
167
184
|
export interface AppServerOptions extends AppOptions {
|
|
@@ -171,69 +188,96 @@ export interface AppServerOptions extends AppOptions {
|
|
|
171
188
|
* the specific server runtime you configure.
|
|
172
189
|
*/
|
|
173
190
|
entry?: string;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Whether to minify the JavaScript outputs for your server.
|
|
194
|
+
*
|
|
195
|
+
* @default false
|
|
196
|
+
*/
|
|
197
|
+
minify?: boolean;
|
|
174
198
|
}
|
|
175
199
|
|
|
176
|
-
export function quiltAppServer({
|
|
200
|
+
export async function quiltAppServer({
|
|
177
201
|
app,
|
|
178
202
|
env,
|
|
179
203
|
graphql,
|
|
180
|
-
entry,
|
|
204
|
+
entry = MAGIC_MODULE_ENTRY,
|
|
205
|
+
minify = false,
|
|
181
206
|
}: AppServerOptions = {}) {
|
|
182
207
|
const mode =
|
|
183
208
|
(typeof env === 'object' ? env?.mode : undefined) ?? 'production';
|
|
184
209
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
210
|
+
const [
|
|
211
|
+
{visualizer},
|
|
212
|
+
{sourceCode},
|
|
213
|
+
{rawAssets, staticAssets},
|
|
214
|
+
{magicModuleRequestRouterEntry},
|
|
215
|
+
nodePlugins,
|
|
216
|
+
] = await Promise.all([
|
|
217
|
+
import('rollup-plugin-visualizer'),
|
|
218
|
+
import('./features/source-code.ts'),
|
|
219
|
+
import('./features/assets.ts'),
|
|
220
|
+
import('./features/request-router.ts'),
|
|
221
|
+
getNodePlugins(),
|
|
222
|
+
]);
|
|
223
|
+
|
|
224
|
+
const plugins: Plugin[] = [
|
|
225
|
+
...nodePlugins,
|
|
226
|
+
sourceCode({mode}),
|
|
227
|
+
rawAssets(),
|
|
228
|
+
staticAssets({emit: false}),
|
|
229
|
+
];
|
|
230
|
+
|
|
231
|
+
if (env) {
|
|
232
|
+
const {magicModuleEnv, replaceProcessEnv} = await import(
|
|
233
|
+
'./features/env.ts'
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
if (typeof env === 'boolean') {
|
|
237
|
+
plugins.push(replaceProcessEnv({mode}));
|
|
238
|
+
plugins.push(magicModuleEnv({mode}));
|
|
239
|
+
} else {
|
|
240
|
+
plugins.push(replaceProcessEnv({mode}));
|
|
241
|
+
plugins.push(magicModuleEnv({mode}));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (app) {
|
|
246
|
+
plugins.push(magicModuleAppComponent({entry: app}));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
plugins.push(magicModuleRequestRouterEntry());
|
|
250
|
+
plugins.push(magicModuleAppRequestRouter({entry}));
|
|
251
|
+
|
|
252
|
+
if (graphql) {
|
|
253
|
+
const {graphql} = await import('./features/graphql.ts');
|
|
254
|
+
plugins.push(graphql({manifest: false}));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (minify) {
|
|
258
|
+
const {minify} = await import('rollup-plugin-esbuild');
|
|
259
|
+
plugins.push(minify());
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
plugins.push(
|
|
263
|
+
visualizer({
|
|
264
|
+
template: 'treemap',
|
|
265
|
+
open: false,
|
|
266
|
+
brotliSize: true,
|
|
267
|
+
filename: path.resolve(`reports/bundle-visualizer.html`),
|
|
268
|
+
}),
|
|
269
|
+
);
|
|
224
270
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
entryFileNames: 'server.js',
|
|
234
|
-
};
|
|
271
|
+
return {
|
|
272
|
+
input: entry,
|
|
273
|
+
plugins,
|
|
274
|
+
output: {
|
|
275
|
+
// format: isESM ? 'esm' : 'systemjs',
|
|
276
|
+
format: 'esm',
|
|
277
|
+
dir: path.resolve(`build/server`),
|
|
278
|
+
entryFileNames: 'server.js',
|
|
235
279
|
},
|
|
236
|
-
} satisfies
|
|
280
|
+
} satisfies RollupOptions;
|
|
237
281
|
}
|
|
238
282
|
|
|
239
283
|
export function magicModuleAppComponent({entry}: {entry: string}) {
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import {readFile} from 'fs/promises';
|
|
3
|
+
import {createHash} from 'crypto';
|
|
4
|
+
|
|
5
|
+
import type {Plugin} from 'rollup';
|
|
6
|
+
import * as mime from 'mrmime';
|
|
7
|
+
|
|
8
|
+
const QUERY_PATTERN = /\?.*$/s;
|
|
9
|
+
const HASH_PATTERN = /#.*$/s;
|
|
10
|
+
const RAW_PATTERN = /(\?|&)raw(?:&|$)/;
|
|
11
|
+
|
|
12
|
+
const DEFAULT_INLINE_LIMIT = 4096;
|
|
13
|
+
const DEFAULT_OUTPUT_PATTERN = '[name].[hash].[ext]';
|
|
14
|
+
const DEFAULT_STATIC_ASSET_EXTENSIONS = [
|
|
15
|
+
// images
|
|
16
|
+
'.png',
|
|
17
|
+
'.jpg',
|
|
18
|
+
'.jpeg',
|
|
19
|
+
'.gif',
|
|
20
|
+
'.svg',
|
|
21
|
+
'.ico',
|
|
22
|
+
'.webp',
|
|
23
|
+
'.avif',
|
|
24
|
+
|
|
25
|
+
// media
|
|
26
|
+
'.mp4',
|
|
27
|
+
'.webm',
|
|
28
|
+
'.ogg',
|
|
29
|
+
'.mp3',
|
|
30
|
+
'.wav',
|
|
31
|
+
'.flac',
|
|
32
|
+
'.aac',
|
|
33
|
+
|
|
34
|
+
// fonts
|
|
35
|
+
'.woff',
|
|
36
|
+
'.woff2',
|
|
37
|
+
'.eot',
|
|
38
|
+
'.ttf',
|
|
39
|
+
'.otf',
|
|
40
|
+
|
|
41
|
+
// other
|
|
42
|
+
'.webmanifest',
|
|
43
|
+
'.pdf',
|
|
44
|
+
'.txt',
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
export function rawAssets(): Plugin {
|
|
48
|
+
return {
|
|
49
|
+
name: '@quilted/raw-assets',
|
|
50
|
+
async load(id) {
|
|
51
|
+
if (id.startsWith('\0') || !RAW_PATTERN.test(id)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const moduleId = cleanModuleIdentifier(id);
|
|
56
|
+
|
|
57
|
+
this.addWatchFile(moduleId);
|
|
58
|
+
|
|
59
|
+
const file = await readFile(moduleId, {
|
|
60
|
+
encoding: 'utf-8',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return `export default ${JSON.stringify(file)}`;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function staticAssets({
|
|
69
|
+
emit = true,
|
|
70
|
+
baseURL = '/',
|
|
71
|
+
extensions = DEFAULT_STATIC_ASSET_EXTENSIONS,
|
|
72
|
+
inlineLimit = DEFAULT_INLINE_LIMIT,
|
|
73
|
+
outputPattern = DEFAULT_OUTPUT_PATTERN,
|
|
74
|
+
}: {
|
|
75
|
+
emit?: boolean;
|
|
76
|
+
baseURL?: string;
|
|
77
|
+
extensions?: readonly string[];
|
|
78
|
+
inlineLimit?: number;
|
|
79
|
+
outputPattern?: string;
|
|
80
|
+
} = {}) {
|
|
81
|
+
const assetCache = new Map<string, string>();
|
|
82
|
+
const assetMatcher = new RegExp(
|
|
83
|
+
`\\.(` +
|
|
84
|
+
extensions
|
|
85
|
+
.map((extension) =>
|
|
86
|
+
extension.startsWith('.') ? extension.slice(1) : extension,
|
|
87
|
+
)
|
|
88
|
+
.join('|') +
|
|
89
|
+
`)(\\?.*)?$`,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
name: '@quilted/static-assets',
|
|
94
|
+
async load(id) {
|
|
95
|
+
if (id.startsWith('\0') || !assetMatcher.test(id)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const cached = assetCache.get(id);
|
|
100
|
+
|
|
101
|
+
if (cached) {
|
|
102
|
+
return cached;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const file = cleanModuleIdentifier(id);
|
|
106
|
+
const content = await readFile(file);
|
|
107
|
+
|
|
108
|
+
let url: string;
|
|
109
|
+
|
|
110
|
+
if (!file.endsWith('.svg') && content.length < inlineLimit) {
|
|
111
|
+
// base64 inlined as a string
|
|
112
|
+
url = `data:${mime.lookup(file)};base64,${content.toString('base64')}`;
|
|
113
|
+
} else {
|
|
114
|
+
const contentHash = getHash(content);
|
|
115
|
+
|
|
116
|
+
const filename = assetFileNamesToFileName(
|
|
117
|
+
outputPattern,
|
|
118
|
+
file,
|
|
119
|
+
contentHash,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
url = `${
|
|
123
|
+
baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL
|
|
124
|
+
}/${filename}`;
|
|
125
|
+
|
|
126
|
+
if (emit) {
|
|
127
|
+
this.emitFile({
|
|
128
|
+
name: file,
|
|
129
|
+
type: 'asset',
|
|
130
|
+
fileName: filename,
|
|
131
|
+
source: content,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const source = `export default ${JSON.stringify(url)};`;
|
|
137
|
+
|
|
138
|
+
assetCache.set(id, source);
|
|
139
|
+
|
|
140
|
+
return source;
|
|
141
|
+
},
|
|
142
|
+
} satisfies Plugin;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function assetFileNamesToFileName(
|
|
146
|
+
pattern: string,
|
|
147
|
+
file: string,
|
|
148
|
+
contentHash: string,
|
|
149
|
+
): string {
|
|
150
|
+
const basename = path.basename(file);
|
|
151
|
+
|
|
152
|
+
const extname = path.extname(basename);
|
|
153
|
+
const ext = extname.substring(1);
|
|
154
|
+
const name = basename.slice(0, -extname.length);
|
|
155
|
+
const hash = contentHash;
|
|
156
|
+
|
|
157
|
+
return pattern.replace(/\[\w+\]/g, (placeholder) => {
|
|
158
|
+
switch (placeholder) {
|
|
159
|
+
case '[ext]':
|
|
160
|
+
return ext;
|
|
161
|
+
|
|
162
|
+
case '[extname]':
|
|
163
|
+
return extname;
|
|
164
|
+
|
|
165
|
+
case '[hash]':
|
|
166
|
+
return hash;
|
|
167
|
+
|
|
168
|
+
case '[name]':
|
|
169
|
+
return name;
|
|
170
|
+
}
|
|
171
|
+
throw new Error(
|
|
172
|
+
`invalid placeholder ${placeholder} in assetFileNames "${pattern}"`,
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function getHash(text: Buffer | string): string {
|
|
178
|
+
return createHash('sha256').update(text).digest('hex').substring(0, 8);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function cleanModuleIdentifier(url: string) {
|
|
182
|
+
return url.replace(HASH_PATTERN, '').replace(QUERY_PATTERN, '');
|
|
183
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type {Plugin} from 'rollup';
|
|
2
|
+
|
|
3
|
+
export interface Options {
|
|
4
|
+
minify?: boolean;
|
|
5
|
+
extract?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const CSS_REGEX = /\.css$/;
|
|
9
|
+
const CSS_MODULE_REGEX = /\.module\.css$/;
|
|
10
|
+
|
|
11
|
+
export function cssRollupPlugin({minify = true, extract = true}: Options) {
|
|
12
|
+
const styles = new Map<string, string>();
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
name: '@quilted/css',
|
|
16
|
+
async transform(code, id) {
|
|
17
|
+
if (!CSS_REGEX.test(id)) return;
|
|
18
|
+
|
|
19
|
+
const {transform} = await import('lightningcss');
|
|
20
|
+
|
|
21
|
+
const transformed = transform({
|
|
22
|
+
filename: id,
|
|
23
|
+
code: new TextEncoder().encode(code),
|
|
24
|
+
cssModules: CSS_MODULE_REGEX.test(id),
|
|
25
|
+
minify,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
styles.set(id, new TextDecoder().decode(transformed.code));
|
|
29
|
+
|
|
30
|
+
const exports = transformed.exports
|
|
31
|
+
? Object.fromEntries(
|
|
32
|
+
Object.entries(transformed.exports).map(([key, exported]) => [
|
|
33
|
+
key,
|
|
34
|
+
exported.name,
|
|
35
|
+
]),
|
|
36
|
+
)
|
|
37
|
+
: undefined;
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
code: exports
|
|
41
|
+
? `export default JSON.parse(${JSON.stringify(
|
|
42
|
+
JSON.stringify(exports),
|
|
43
|
+
)})`
|
|
44
|
+
: `export default undefined;`,
|
|
45
|
+
map: {mappings: ''},
|
|
46
|
+
moduleSideEffects: 'no-treeshake',
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
async renderChunk(_, chunk) {
|
|
50
|
+
if (!extract) return null;
|
|
51
|
+
|
|
52
|
+
let chunkCss = '';
|
|
53
|
+
|
|
54
|
+
for (const id of Object.keys(chunk.modules)) {
|
|
55
|
+
if (CSS_REGEX.test(id) && styles.has(id)) {
|
|
56
|
+
chunkCss += styles.get(id);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (chunkCss.length === 0) return null;
|
|
61
|
+
|
|
62
|
+
const code = chunkCss;
|
|
63
|
+
|
|
64
|
+
// if (minify) {
|
|
65
|
+
// const {default: CleanCSS} = await import('clean-css');
|
|
66
|
+
|
|
67
|
+
// const cleaner = new CleanCSS({
|
|
68
|
+
// rebase: false,
|
|
69
|
+
// });
|
|
70
|
+
|
|
71
|
+
// const minified = cleaner.minify(chunkCss);
|
|
72
|
+
|
|
73
|
+
// if (minified.errors.length > 0) {
|
|
74
|
+
// throw minified.errors[0];
|
|
75
|
+
// }
|
|
76
|
+
|
|
77
|
+
// code = minified.styles;
|
|
78
|
+
// }
|
|
79
|
+
|
|
80
|
+
const fileHandle = this.emitFile({
|
|
81
|
+
type: 'asset',
|
|
82
|
+
name: `${chunk.fileName.split('.')[0]}.css`,
|
|
83
|
+
source: code,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
chunk.imports.push(this.getFileName(fileHandle));
|
|
87
|
+
|
|
88
|
+
return null;
|
|
89
|
+
},
|
|
90
|
+
} satisfies Plugin;
|
|
91
|
+
}
|
|
@@ -3,10 +3,10 @@ import * as fs from 'fs';
|
|
|
3
3
|
|
|
4
4
|
import type {PluginContext} from 'rollup';
|
|
5
5
|
|
|
6
|
-
import {MAGIC_MODULE_ENV} from '
|
|
7
|
-
import {multiline} from '
|
|
8
|
-
import {smartReplace} from '
|
|
9
|
-
import {createMagicModulePlugin} from '
|
|
6
|
+
import {MAGIC_MODULE_ENV} from '../constants.ts';
|
|
7
|
+
import {multiline} from '../shared/strings.ts';
|
|
8
|
+
import {smartReplace} from '../shared/rollup.ts';
|
|
9
|
+
import {createMagicModulePlugin} from '../shared/magic-module.ts';
|
|
10
10
|
|
|
11
11
|
const EMPTY_PROCESS_ENV_OBJECT = {
|
|
12
12
|
'globalThis.process.env.': `({}).`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {MAGIC_MODULE_ENTRY, MAGIC_MODULE_REQUEST_ROUTER} from '
|
|
1
|
+
import {MAGIC_MODULE_ENTRY, MAGIC_MODULE_REQUEST_ROUTER} from '../constants.ts';
|
|
2
2
|
|
|
3
|
-
import {createMagicModulePlugin} from '
|
|
4
|
-
import {multiline} from '
|
|
3
|
+
import {createMagicModulePlugin} from '../shared/magic-module.ts';
|
|
4
|
+
import {multiline} from '../shared/strings.ts';
|
|
5
5
|
|
|
6
6
|
export function magicModuleRequestRouterEntry({
|
|
7
7
|
host,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {readFile} from 'fs/promises';
|
|
2
|
+
import {createRequire} from 'module';
|
|
3
|
+
|
|
4
|
+
import type {Plugin} from 'rollup';
|
|
5
|
+
|
|
6
|
+
export function systemJS({minify = false} = {}) {
|
|
7
|
+
return {
|
|
8
|
+
name: '@quilted/system-js',
|
|
9
|
+
async renderChunk(_, chunk, options) {
|
|
10
|
+
if (options.format !== 'system' || !chunk.isEntry) return null;
|
|
11
|
+
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const systemjs = minify
|
|
14
|
+
? require.resolve('systemjs/dist/s.min.js')
|
|
15
|
+
: require.resolve('systemjs/dist/s.js');
|
|
16
|
+
|
|
17
|
+
// We write the systemjs loader to a dedicated file, and we make it the
|
|
18
|
+
// "first import" of the chunk so that it is the first file listed in
|
|
19
|
+
// the manifest.
|
|
20
|
+
const fileHandle = this.emitFile({
|
|
21
|
+
type: 'asset',
|
|
22
|
+
name: 'loader.js',
|
|
23
|
+
source: (await readFile(systemjs, {encoding: 'utf8'})).replace(
|
|
24
|
+
// Remove the source map comment, if it is present, because we don’t upload the
|
|
25
|
+
// sourcemap for this file.
|
|
26
|
+
/\n?[/][/]# sourceMappingURL=s.*\.map\n?$/,
|
|
27
|
+
'',
|
|
28
|
+
),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
chunk.imports.unshift(this.getFileName(fileHandle));
|
|
32
|
+
|
|
33
|
+
return null;
|
|
34
|
+
},
|
|
35
|
+
} satisfies Plugin;
|
|
36
|
+
}
|