Skip to content

Commit

Permalink
feat(qwikVite): add possibility to define multiple outputs (#6452)
Browse files Browse the repository at this point in the history
* add possibility to define multiple outputs in vite

* more explicit assertions in tests

* simplify code

* small improvement to make sure at least one output is present in every case

* change variable name so the history is easier to follow

* fix(vite.unit.ts): grab plugin

---------

Co-authored-by: PatrickJS <github@gdi2290.com>
  • Loading branch information
KingSora and PatrickJS authored Jun 14, 2024
1 parent b380973 commit 97dbcaa
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 31 deletions.
29 changes: 24 additions & 5 deletions packages/qwik/src/optimizer/src/plugins/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function qwikRollup(qwikRollupOpts: QwikRollupPluginOptions = {}): any {
},

outputOptions(rollupOutputOpts) {
return normalizeRollupOutputOptions(
return normalizeRollupOutputOptionsObject(
qwikPlugin.getPath(),
qwikPlugin.getOptions(),
rollupOutputOpts
Expand Down Expand Up @@ -168,11 +168,30 @@ export function normalizeRollupOutputOptions(
path: Path,
opts: NormalizedQwikPluginOptions,
rollupOutputOpts: Rollup.OutputOptions | Rollup.OutputOptions[] | undefined
) {
const outputOpts: Rollup.OutputOptions = {};
if (rollupOutputOpts && !Array.isArray(rollupOutputOpts)) {
Object.assign(outputOpts, rollupOutputOpts);
): Rollup.OutputOptions[] {
const outputOpts: Rollup.OutputOptions[] = Array.isArray(rollupOutputOpts)
? // fill the `outputOpts` array with all existing option entries
[...rollupOutputOpts]
: // use the existing rollupOutputOpts object or create a new one
[rollupOutputOpts || {}];

// make sure at least one output is present in every case
if (!outputOpts.length) {
outputOpts.push({});
}

return outputOpts.map((outputOptsObj) =>
normalizeRollupOutputOptionsObject(path, opts, outputOptsObj)
);
}

export function normalizeRollupOutputOptionsObject(
path: Path,
opts: NormalizedQwikPluginOptions,
rollupOutputOptsObj: Rollup.OutputOptions | undefined
): Rollup.OutputOptions {
const outputOpts: Rollup.OutputOptions = { ...rollupOutputOptsObj };

if (!outputOpts.assetFileNames) {
outputOpts.assetFileNames = 'build/q-[hash].[ext]';
}
Expand Down
12 changes: 8 additions & 4 deletions packages/qwik/src/optimizer/src/plugins/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,14 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
updatedViteConfig.build!.outDir = buildOutputDir;
updatedViteConfig.build!.rollupOptions = {
input: opts.input,
output: {
...normalizeRollupOutputOptions(path, opts, viteConfig.build?.rollupOptions?.output),
dir: buildOutputDir,
},
output: normalizeRollupOutputOptions(
path,
opts,
viteConfig.build?.rollupOptions?.output
).map((outputOptsObj) => {
outputOptsObj.dir = buildOutputDir;
return outputOptsObj;
}),
preserveEntrySignatures: 'exports-only',
onwarn: (warning, warn) => {
if (warning.plugin === 'typescript' && warning.message.includes('outputToFilesystem')) {
Expand Down
148 changes: 126 additions & 22 deletions packages/qwik/src/optimizer/src/plugins/vite.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ test('command: serve, mode: development', async () => {
const opts = await plugin.api?.getOptions();
const build = c.build!;
const rollupOptions = build!.rollupOptions!;
const outputOptions = rollupOptions.output as Rollup.OutputOptions;
const outputOptions = rollupOptions.output as Rollup.OutputOptions[];

assert.deepEqual(opts.target, 'client');
assert.deepEqual(opts.buildMode, 'development');
Expand All @@ -61,10 +61,17 @@ test('command: serve, mode: development', async () => {

assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist')));
assert.deepEqual(rollupOptions.input, normalizePath(resolve(cwd, 'src', 'entry.dev')));
assert.deepEqual(outputOptions.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptions.chunkFileNames, 'build/[name].js');
assert.deepEqual(outputOptions.entryFileNames, 'build/[name].js');
assert.deepEqual(outputOptions.format, 'es');

assert.ok(Array.isArray(outputOptions));
assert.lengthOf(outputOptions, 1);

outputOptions.forEach((outputOptionsObj) => {
assert.deepEqual(outputOptionsObj.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptionsObj.chunkFileNames, 'build/[name].js');
assert.deepEqual(outputOptionsObj.entryFileNames, 'build/[name].js');
assert.deepEqual(outputOptionsObj.format, 'es');
});

assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]);
assert.deepEqual(build.ssr, undefined);
assert.deepEqual(c.optimizeDeps?.include, includeDeps);
Expand All @@ -85,7 +92,7 @@ test('command: serve, mode: production', async () => {
const opts = await plugin.api?.getOptions();
const build = c.build!;
const rollupOptions = build!.rollupOptions!;
const outputOptions = rollupOptions.output as Rollup.OutputOptions;
const outputOptions = rollupOptions.output as Rollup.OutputOptions[];

assert.deepEqual(opts.target, 'client');
assert.deepEqual(opts.buildMode, 'production');
Expand All @@ -96,10 +103,17 @@ test('command: serve, mode: production', async () => {
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist')));
assert.deepEqual(build.emptyOutDir, undefined);
assert.deepEqual(rollupOptions.input, normalizePath(resolve(cwd, 'src', 'entry.dev')));
assert.deepEqual(outputOptions.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptions.chunkFileNames, 'build/q-[hash].js');
assert.deepEqual(outputOptions.entryFileNames, 'build/q-[hash].js');
assert.deepEqual(outputOptions.format, 'es');

assert.ok(Array.isArray(outputOptions));
assert.lengthOf(outputOptions, 1);

outputOptions.forEach((outputOptionsObj) => {
assert.deepEqual(outputOptionsObj.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptionsObj.chunkFileNames, 'build/q-[hash].js');
assert.deepEqual(outputOptionsObj.entryFileNames, 'build/q-[hash].js');
assert.deepEqual(outputOptionsObj.format, 'es');
});

assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]);
assert.deepEqual(build.ssr, undefined);
assert.deepEqual(c.optimizeDeps?.include, includeDeps);
Expand All @@ -119,7 +133,7 @@ test('command: build, mode: development', async () => {
const opts = await plugin.api?.getOptions();
const build = c.build!;
const rollupOptions = build!.rollupOptions!;
const outputOptions = rollupOptions.output as Rollup.OutputOptions;
const outputOptions = rollupOptions.output as Rollup.OutputOptions[];

assert.deepEqual(opts.target, 'client');
assert.deepEqual(opts.buildMode, 'development');
Expand All @@ -131,9 +145,16 @@ test('command: build, mode: development', async () => {
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist')));
assert.deepEqual(build.emptyOutDir, undefined);
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'root'))]);
assert.deepEqual(outputOptions.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptions.chunkFileNames, 'build/[name].js');
assert.deepEqual(outputOptions.entryFileNames, 'build/[name].js');

assert.ok(Array.isArray(outputOptions));
assert.lengthOf(outputOptions, 1);

outputOptions.forEach((outputOptionsObj) => {
assert.deepEqual(outputOptionsObj.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptionsObj.chunkFileNames, 'build/[name].js');
assert.deepEqual(outputOptionsObj.entryFileNames, 'build/[name].js');
});

assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]);
assert.deepEqual(build.ssr, undefined);
assert.deepEqual(c.optimizeDeps?.include, includeDeps);
Expand All @@ -156,7 +177,7 @@ test('command: build, mode: production', async () => {
const opts = await plugin.api?.getOptions();
const build = c.build!;
const rollupOptions = build!.rollupOptions!;
const outputOptions = rollupOptions.output as Rollup.OutputOptions;
const outputOptions = rollupOptions.output as Rollup.OutputOptions[];

assert.deepEqual(opts.target, 'client');
assert.deepEqual(opts.buildMode, 'production');
Expand All @@ -168,9 +189,16 @@ test('command: build, mode: production', async () => {
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist')));
assert.deepEqual(build.emptyOutDir, undefined);
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'root'))]);
assert.deepEqual(outputOptions.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptions.chunkFileNames, 'build/q-[hash].js');
assert.deepEqual(outputOptions.entryFileNames, 'build/q-[hash].js');

assert.ok(Array.isArray(outputOptions));
assert.lengthOf(outputOptions, 1);

outputOptions.forEach((outputOptionsObj) => {
assert.deepEqual(outputOptionsObj.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptionsObj.chunkFileNames, 'build/q-[hash].js');
assert.deepEqual(outputOptionsObj.entryFileNames, 'build/q-[hash].js');
});

assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist')));
assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]);
assert.deepEqual(build.ssr, undefined);
Expand Down Expand Up @@ -220,7 +248,7 @@ test('command: build, --ssr entry.server.tsx', async () => {
const opts = await plugin.api?.getOptions();
const build = c.build!;
const rollupOptions = build!.rollupOptions!;
const outputOptions = rollupOptions.output as Rollup.OutputOptions;
const outputOptions = rollupOptions.output as Rollup.OutputOptions[];

assert.deepEqual(opts.target, 'ssr');
assert.deepEqual(opts.buildMode, 'development');
Expand All @@ -232,9 +260,16 @@ test('command: build, --ssr entry.server.tsx', async () => {
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'server')));
assert.deepEqual(build.emptyOutDir, undefined);
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'entry.server.tsx'))]);
assert.deepEqual(outputOptions.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptions.chunkFileNames, undefined);
assert.deepEqual(outputOptions.entryFileNames, undefined);

assert.ok(Array.isArray(outputOptions));
assert.lengthOf(outputOptions, 1);

outputOptions.forEach((outputOptionsObj) => {
assert.deepEqual(outputOptionsObj.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptionsObj.chunkFileNames, undefined);
assert.deepEqual(outputOptionsObj.entryFileNames, undefined);
});

assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'server')));
assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]);
assert.deepEqual(build.ssr, true);
Expand Down Expand Up @@ -348,12 +383,81 @@ test('command: build, --mode lib', async () => {
const opts = await plugin.api?.getOptions();
const build = c.build!;
const rollupOptions = build!.rollupOptions!;
const outputOptions = rollupOptions.output as Rollup.OutputOptions[];

assert.deepEqual(opts.target, 'lib');
assert.deepEqual(opts.buildMode, 'development');
assert.deepEqual(build.minify, false);
assert.deepEqual(build.ssr, undefined);
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'index.ts'))]);

assert.ok(Array.isArray(outputOptions));
assert.lengthOf(outputOptions, 1);

outputOptions.forEach((outputOptionsObj) => {
assert.deepEqual(outputOptionsObj.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptionsObj.chunkFileNames, undefined);
});

assert.deepEqual(c.build.outDir, normalizePath(resolve(cwd, 'lib')));
assert.deepEqual(build.emptyOutDir, undefined);
assert.deepEqual(opts.resolveQwikBuild, true);
});

test('command: build, --mode lib with multiple outputs', async () => {
const initOpts = {
optimizerOptions: mockOptimizerOptions(),
};
const plugin = qwikVite(initOpts)[0];
const c: any = (await plugin.config(
{
build: {
lib: {
entry: './src/index.ts',
},
rollupOptions: {
output: [
{
format: 'es',
entryFileNames: 'index.esm.js',
},
{
format: 'es',
entryFileNames: 'index.mjs',
},
{
format: 'cjs',
entryFileNames: 'index.cjs.js',
},
{
format: 'cjs',
entryFileNames: 'index.cjs',
},
],
},
},
},
{ command: 'build', mode: 'lib' }
))!;
const opts = await plugin.api?.getOptions();
const build = c.build!;
const rollupOptions = build!.rollupOptions!;
const outputOptions = rollupOptions.output as Rollup.OutputOptions[];

assert.deepEqual(opts.target, 'lib');
assert.deepEqual(opts.buildMode, 'development');
assert.deepEqual(build.minify, false);
assert.deepEqual(build.ssr, undefined);
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'index.ts'))]);

assert.ok(Array.isArray(outputOptions));
assert.lengthOf(outputOptions, 4);

outputOptions.forEach((outputOptionsObj) => {
assert.deepEqual(outputOptionsObj.assetFileNames, 'build/q-[hash].[ext]');
assert.deepEqual(outputOptionsObj.chunkFileNames, undefined);
});

assert.deepEqual(c.build.outDir, normalizePath(resolve(cwd, 'lib')));
assert.deepEqual(build.emptyOutDir, undefined);
assert.deepEqual(opts.resolveQwikBuild, true);
Expand Down

0 comments on commit 97dbcaa

Please sign in to comment.