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

Passing the Rollup output options through to Vite #1572

Merged
merged 13 commits into from
Jun 14, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 39 additions & 22 deletions packages/kit/src/core/build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import fs from 'fs';
import path from 'path';
import { rimraf } from '../filesystem/index.js';
import create_manifest_data from '../../core/create_manifest_data/index.js';
import { copy_assets, get_no_external, posixify, resolve_entry } from '../utils.js';
import { copy_assets, get_no_external, posixify, resolve_entry, deep_merge } from '../utils.js';
import { create_app } from '../../core/create_app/index.js';
import vite from 'vite';
import svelte from '@sveltejs/vite-plugin-svelte';
import glob from 'tiny-glob/sync.js';
import { SVELTE_KIT } from '../constants.js';
import colors from 'kleur';

/** @param {any} value */
const s = (value) => JSON.stringify(value);
Expand Down Expand Up @@ -77,6 +78,25 @@ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/
};
}

/**
* @param {string?} scope used to prefix the error message
* @param {string[]} conflicts array of conflicts in dotted notation
*/
function print_vite_config_conflicts(scope, conflicts) {
benmccann marked this conversation as resolved.
Show resolved Hide resolved
const prefix = scope ? scope + ': ' : '';
conflicts.forEach((conflict) => {
console.error(
colors
.bold()
.red(
`${prefix}The value for ${colors.italic(
`kit.vite.${conflict}`
)} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.`
)
);
});
}

/**
* @param {{
* cwd: string;
Expand Down Expand Up @@ -134,19 +154,17 @@ async function build_client({
/** @type {any} */
const user_config = config.kit.vite();

await vite.build({
...user_config,
/** @type {[any, string[]]} */
const [merged_config, conflicts] = deep_merge(user_config, {
configFile: false,
root: cwd,
base,
build: {
...user_config.build,
cssCodeSplit: true,
manifest: true,
outDir: client_out_dir,
polyfillDynamicImport: false,
rollupOptions: {
...(user_config.build && user_config.build.rollupOptions),
input,
output: {
entryFileNames: '[name]-[hash].js',
Expand All @@ -157,22 +175,23 @@ async function build_client({
}
},
resolve: {
...user_config.resolve,
alias: {
...(user_config.resolve && user_config.resolve.alias),
$app: path.resolve(`${build_dir}/runtime/app`),
$lib: config.kit.files.lib
}
},
plugins: [
...(user_config.plugins || []),
svelte({
extensions: config.extensions,
emitCss: !config.kit.amp
})
]
});

print_vite_config_conflicts('build_client', conflicts);

await vite.build(merged_config);

/** @type {ClientManifest} */
const client_manifest = JSON.parse(fs.readFileSync(client_manifest_file, 'utf-8'));
fs.renameSync(client_manifest_file, `${output_dir}/manifest.json`); // inspectable but not shipped
Expand Down Expand Up @@ -395,19 +414,17 @@ async function build_server(
/** @type {any} */
const user_config = config.kit.vite();

await vite.build({
...user_config,
/** @type {[any, string[]]} */
const [merged_config, conflicts] = deep_merge(user_config, {
configFile: false,
root: cwd,
base,
build: {
target: 'es2018',
...user_config.build,
ssr: true,
outDir: `${output_dir}/server`,
polyfillDynamicImport: false,
rollupOptions: {
...(user_config.build && user_config.build.rollupOptions),
input: {
app: app_file
},
Expand All @@ -422,15 +439,12 @@ async function build_server(
}
},
resolve: {
...user_config.resolve,
alias: {
...(user_config.resolve && user_config.resolve.alias),
$app: path.resolve(`${build_dir}/runtime/app`),
$lib: config.kit.files.lib
}
},
plugins: [
...(user_config.plugins || []),
svelte({
extensions: config.extensions
})
Expand All @@ -440,7 +454,6 @@ async function build_server(
// so we need to ignore the fact that it's missing
// @ts-ignore
ssr: {
...user_config.ssr,
// note to self: this _might_ need to be ['svelte', '@sveltejs/kit', ...get_no_external()]
// but I'm honestly not sure. roll with this for now and see if it's ok
noExternal: get_no_external(cwd, user_config.ssr && user_config.ssr.noExternal)
Expand All @@ -449,6 +462,10 @@ async function build_server(
entries: []
}
});

print_vite_config_conflicts('build_server', conflicts);

await vite.build(merged_config);
}

/**
Expand Down Expand Up @@ -504,20 +521,18 @@ async function build_service_worker(
/** @type {any} */
const user_config = config.kit.vite();

await vite.build({
...user_config,
/** @type {[any, string[]]} */
const [merged_config, conflicts] = deep_merge(user_config, {
configFile: false,
root: cwd,
base,
build: {
...user_config.build,
lib: {
entry: service_worker_entry_file,
name: 'app',
formats: ['es']
},
rollupOptions: {
...(user_config.build && user_config.build.rollupOptions),
output: {
entryFileNames: 'service-worker.js'
}
Expand All @@ -526,16 +541,18 @@ async function build_service_worker(
emptyOutDir: false
},
resolve: {
...user_config.resolve,
alias: {
...(user_config.resolve && user_config.resolve.alias),
'$service-worker': path.resolve(`${build_dir}/runtime/service-worker`)
}
},
optimizeDeps: {
entries: []
}
});

print_vite_config_conflicts('build_service_worker', conflicts);

await vite.build(merged_config);
}

/** @param {string[]} array */
Expand Down
33 changes: 20 additions & 13 deletions packages/kit/src/core/dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { create_app } from '../../core/create_app/index.js';
import { rimraf } from '../filesystem/index.js';
import { respond } from '../../runtime/server/index.js';
import { getRawBody } from '../node/index.js';
import { copy_assets, get_no_external, resolve_entry } from '../utils.js';
import { copy_assets, get_no_external, resolve_entry, deep_merge } from '../utils.js';
import svelte from '@sveltejs/vite-plugin-svelte';
import { get_server } from '../server/index.js';
import '../../install-fetch.js';
Expand Down Expand Up @@ -84,47 +84,54 @@ class Watcher extends EventEmitter {

this.server = await get_server(this.https, user_config, (req, res) => handler(req, res));

/**
* @type {vite.ViteDevServer}
*/
this.vite = await vite.createServer({
...user_config,
/** @type {[any, string[]]} */
const [merged_config, conflicts] = deep_merge(user_config, {
configFile: false,
root: this.cwd,
resolve: {
...user_config.resolve,
alias: {
...(user_config.resolve && user_config.resolve.alias),
$app: path.resolve(`${this.dir}/runtime/app`),
$lib: this.config.kit.files.lib
}
},
plugins: [
...(user_config.plugins || []),
svelte({
extensions: this.config.extensions,
emitCss: !this.config.kit.amp
})
],
publicDir: this.config.kit.files.assets,
server: {
...user_config.server,
middlewareMode: true,
hmr: {
...(user_config.server && user_config.server.hmr),
...(this.https ? { server: this.server, port: this.port } : {})
}
},
optimizeDeps: {
...user_config.optimizeDeps,
entries: []
},
ssr: {
...user_config.ssr,
noExternal: get_no_external(this.cwd, user_config.ssr && user_config.ssr.noExternal)
}
});

conflicts.forEach((conflict) => {
Copy link
Member

Choose a reason for hiding this comment

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

could we put the print_vite_config_conflicts method somewhere shared and use it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool, how about a generic "print_config_conflicts" that might as well use the logger() I suppose. See update.

console.error(
colors
.bold()
.red(
`The value for ${colors.italic(
`kit.vite.${conflict}`
)} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.`
)
);
});

/**
* @type {vite.ViteDevServer}
*/
this.vite = await vite.createServer(merged_config);

const validator = this.config.kit.amp && (await amp_validator.getInstance());

/**
Expand Down
58 changes: 58 additions & 0 deletions packages/kit/src/core/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,61 @@ function find_svelte_packages(cwd) {
export function get_no_external(cwd, user_specified_deps = []) {
return [...user_specified_deps, ...find_svelte_packages(cwd)];
}

/**
* Merges b into a, recursively, mutating a.
* @param {Record<string, any>} a
* @param {Record<string, any>} b
* @param {string[]} conflicts array to accumulate conflicts in
* @param {string[]} path array of property names representing the current
* location in the tree
*/
function merge_into(a, b, conflicts = [], path = []) {
/**
* @param {any} x
*/
const is_object = (x) => typeof x === 'object' && !Array.isArray(x);

for (const prop in b) {
if (is_object(b[prop])) {
if (!is_object(a[prop])) {
if (a[prop] !== undefined) {
conflicts.push([...path, prop].join('.'));
}
a[prop] = {};
}
merge_into(a[prop], b[prop], conflicts, [...path, prop]);
} else if (Array.isArray(b[prop])) {
if (!Array.isArray(a[prop])) {
if (a[prop] !== undefined) {
conflicts.push([...path, prop].join('.'));
}
a[prop] = [];
}
a[prop].push(...b[prop]);
} else {
if (a[prop] !== undefined) {
conflicts.push([...path, prop].join('.'));
}
a[prop] = b[prop];
}
}
}

/**
* Takes zero or more objects and returns a new object that has all the values
* deeply merged together. None of the original objects will be mutated at any
* level, and the returned object will have no references to the original
* objects at any depth. If there's a conflict the last one wins, except for
* arrays which will be combined.
* @param {...Object} objects
* @returns {[Record<string, any>, string[]]} a 2-tuple with the merged object,
* and a list of merge conflicts if there were any, in dotted notation
*/
export function deep_merge(...objects) {
const result = {};
/** @type {string[]} */
const conflicts = [];
objects.forEach((o) => merge_into(result, o, conflicts));
return [result, conflicts];
}
Loading