From 1a7c0da8716530b41bb389084188f73d11b5ef20 Mon Sep 17 00:00:00 2001 From: Yoshito Komatsu Date: Sat, 8 Jan 2022 00:26:06 +0900 Subject: [PATCH] Improve error message when a Svelte config is not found (#3219) * Improve an error message for MODULE_NOT_FOUND * Add a changeset * Update a changeset Co-authored-by: Bjorn Lu * Move some error messages * Move some error messages again * Update * remove support for svelte.config.cjs * tweak changeset * simplify config error handling * simplify further * lint * update test Co-authored-by: Bjorn Lu Co-authored-by: Rich Harris --- .changeset/neat-points-exercise.md | 5 ++ packages/kit/package.json | 1 + packages/kit/src/cli.js | 82 ++++++------------- packages/kit/src/core/config/index.js | 24 +++--- .../fixtures/default-cjs/svelte.config.cjs | 0 .../{default-esm => default}/svelte.config.js | 0 packages/kit/src/core/config/test/index.js | 24 ++---- .../test/fixtures/resolve-alias/package.json | 3 +- .../fixtures/resolve-alias/svelte.config.cjs | 5 -- .../fixtures/resolve-alias/svelte.config.js | 5 ++ .../test/fixtures/typescript/package.json | 3 +- .../fixtures/typescript/svelte.config.cjs | 5 -- .../test/fixtures/typescript/svelte.config.js | 5 ++ pnpm-lock.yaml | 2 + 14 files changed, 62 insertions(+), 102 deletions(-) create mode 100644 .changeset/neat-points-exercise.md delete mode 100644 packages/kit/src/core/config/test/fixtures/default-cjs/svelte.config.cjs rename packages/kit/src/core/config/test/fixtures/{default-esm => default}/svelte.config.js (100%) delete mode 100644 packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.cjs create mode 100644 packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.js delete mode 100644 packages/kit/src/packaging/test/fixtures/typescript/svelte.config.cjs create mode 100644 packages/kit/src/packaging/test/fixtures/typescript/svelte.config.js diff --git a/.changeset/neat-points-exercise.md b/.changeset/neat-points-exercise.md new file mode 100644 index 000000000000..ebfb2f95bc5d --- /dev/null +++ b/.changeset/neat-points-exercise.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +Improve error message when svelte.config.js is not found diff --git a/packages/kit/package.json b/packages/kit/package.json index fd45b73462d7..db5d2aa23e4c 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -39,6 +39,7 @@ "sirv": "^1.0.19", "svelte": "^3.44.2", "svelte-check": "^2.2.10", + "svelte-preprocess": "^4.9.8", "svelte2tsx": "~0.4.10", "tiny-glob": "^0.2.9", "uvu": "^0.5.2" diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 3641406f225c..075731d62c29 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -1,58 +1,22 @@ -import { existsSync } from 'fs'; import sade from 'sade'; import colors from 'kleur'; import { relative } from 'path'; import * as ports from 'port-authority'; import { load_config } from './core/config/index.js'; import { networkInterfaces, release } from 'os'; -import { coalesce_to_error, has_error_code } from './utils/error.js'; +import { coalesce_to_error } from './utils/error.js'; -async function get_config() { - // TODO this is temporary, for the benefit of early adopters - if (existsSync('svelte.config.cjs')) { - // prettier-ignore - console.error(colors.bold().red( - 'svelte.config.cjs should be renamed to svelte.config.js and converted to an ES module. See https://kit.svelte.dev/docs#configuration for an example' - )); - } +/** @param {unknown} e */ +function handle_error(e) { + const error = coalesce_to_error(e); - if (existsSync('vite.config.js')) { - // prettier-ignore - console.error(colors.bold().red( - 'Please remove vite.config.js and put Vite config in svelte.config.js: https://kit.svelte.dev/docs#configuration-vite' - )); - } + if (error.name === 'SyntaxError') throw error; - try { - return await load_config(); - } catch (err) { - const error = coalesce_to_error(err); - let message = error.message; - - if ( - has_error_code(error, 'MODULE_NOT_FOUND') && - /Cannot find module svelte\.config\./.test(error.message) - ) { - message = 'Missing svelte.config.js'; - } else if (error.name === 'SyntaxError') { - message = 'Malformed svelte.config.js'; - } - - console.error(colors.bold().red(message)); - if (error.stack) { - console.error(colors.grey(error.stack)); - } - process.exit(1); + console.log(colors.bold().red(`> ${error.message}`)); + if (error.stack) { + console.log(colors.gray(error.stack.split('\n').slice(1).join('\n'))); } -} -/** @param {unknown} error */ -function handle_error(error) { - const err = coalesce_to_error(error); - console.log(colors.bold().red(`> ${err.message}`)); - if (err.stack) { - console.log(colors.gray(err.stack)); - } process.exit(1); } @@ -85,12 +49,12 @@ prog .option('-H, --https', 'Use self-signed HTTPS certificate') .option('-o, --open', 'Open a browser tab') .action(async ({ port, host, https, open }) => { - process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - const config = await get_config(); + try { + process.env.NODE_ENV = process.env.NODE_ENV || 'development'; + const config = await load_config(); - const { dev } = await import('./core/dev/index.js'); + const { dev } = await import('./core/dev/index.js'); - try { const cwd = process.cwd(); const { address_info, server_config } = await dev({ @@ -120,10 +84,10 @@ prog .describe('Create a production build of your app') .option('--verbose', 'Log more stuff', false) .action(async ({ verbose }) => { - process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - const config = await get_config(); - try { + process.env.NODE_ENV = process.env.NODE_ENV || 'production'; + const config = await load_config(); + const { build } = await import('./core/build/index.js'); const build_data = await build(config); @@ -158,14 +122,14 @@ prog .option('-H, --https', 'Use self-signed HTTPS certificate', false) .option('-o, --open', 'Open a browser tab', false) .action(async ({ port, host, https, open }) => { - await check_port(port); + try { + await check_port(port); - process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - const config = await get_config(); + process.env.NODE_ENV = process.env.NODE_ENV || 'production'; + const config = await load_config(); - const { preview } = await import('./core/preview/index.js'); + const { preview } = await import('./core/preview/index.js'); - try { await preview({ port, host, config, https }); welcome({ port, host, https, open }); @@ -179,11 +143,11 @@ prog .describe('Create a package') .option('-d, --dir', 'Destination directory', 'package') .action(async () => { - const config = await get_config(); + try { + const config = await load_config(); - const { make_package } = await import('./packaging/index.js'); + const { make_package } = await import('./packaging/index.js'); - try { await make_package(config); } catch (error) { handle_error(error); diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index dcf18eefec8e..98e98158153e 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -28,10 +28,14 @@ export function load_template(cwd, config) { } export async function load_config({ cwd = process.cwd() } = {}) { - const config_file_esm = path.join(cwd, 'svelte.config.js'); - const config_file = fs.existsSync(config_file_esm) - ? config_file_esm - : path.join(cwd, 'svelte.config.cjs'); + const config_file = path.join(cwd, 'svelte.config.js'); + + if (!fs.existsSync(config_file)) { + throw new Error( + 'You need to create a svelte.config.js file. See https://kit.svelte.dev/docs#configuration' + ); + } + const config = await import(url.pathToFileURL(config_file).href); const validated = validate_config(config.default); @@ -51,17 +55,9 @@ export async function load_config({ cwd = process.cwd() } = {}) { * @returns {import('types/config').ValidatedConfig} */ export function validate_config(config) { - const type = typeof config; - - if (type === 'undefined') { - throw new Error( - 'Your config is missing default exports. Make sure to include "export default config;"' - ); - } - - if (type !== 'object') { + if (typeof config !== 'object') { throw new Error( - `Unexpected config type "${type}", make sure your default export is an object.` + 'svelte.config.js must have a configuration object as its default export. See https://kit.svelte.dev/docs#configuration' ); } diff --git a/packages/kit/src/core/config/test/fixtures/default-cjs/svelte.config.cjs b/packages/kit/src/core/config/test/fixtures/default-cjs/svelte.config.cjs deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/kit/src/core/config/test/fixtures/default-esm/svelte.config.js b/packages/kit/src/core/config/test/fixtures/default/svelte.config.js similarity index 100% rename from packages/kit/src/core/config/test/fixtures/default-esm/svelte.config.js rename to packages/kit/src/core/config/test/fixtures/default/svelte.config.js diff --git a/packages/kit/src/core/config/test/index.js b/packages/kit/src/core/config/test/index.js index 79ecf067dd38..4b5a96d408e5 100644 --- a/packages/kit/src/core/config/test/index.js +++ b/packages/kit/src/core/config/test/index.js @@ -10,11 +10,8 @@ import { load_config } from '../index.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = join(__filename, '..'); -/** - * @param {string} path - */ -async function testLoadDefaultConfig(path) { - const cwd = join(__dirname, 'fixtures', path); +test('load default config (esm)', async () => { + const cwd = join(__dirname, 'fixtures/default'); const config = await load_config({ cwd }); remove_keys(config, ([, v]) => typeof v === 'function'); @@ -64,28 +61,21 @@ async function testLoadDefaultConfig(path) { trailingSlash: 'never' } }); -} - -test('load default config (cjs)', async () => { - await testLoadDefaultConfig('default-cjs'); -}); - -test('load default config (esm)', async () => { - await testLoadDefaultConfig('default-esm'); }); test('errors on loading config with incorrect default export', async () => { - let errorMessage = null; + let message = null; + try { const cwd = join(__dirname, 'fixtures', 'export-string'); await load_config({ cwd }); } catch (/** @type {any} */ e) { - errorMessage = e.message; + message = e.message; } assert.equal( - errorMessage, - 'Unexpected config type "string", make sure your default export is an object.' + message, + 'svelte.config.js must have a configuration object as its default export. See https://kit.svelte.dev/docs#configuration' ); }); diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/package.json b/packages/kit/src/packaging/test/fixtures/resolve-alias/package.json index 65358d9a9a8a..eec695b67186 100644 --- a/packages/kit/src/packaging/test/fixtures/resolve-alias/package.json +++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/package.json @@ -1,5 +1,6 @@ { "name": "resolve-alias", "version": "1.0.0", - "description": "package using $lib alias" + "description": "package using $lib alias", + "type": "module" } diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.cjs b/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.cjs deleted file mode 100644 index d0526bbb674d..000000000000 --- a/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.cjs +++ /dev/null @@ -1,5 +0,0 @@ -const preprocess = require('svelte-preprocess'); - -module.exports = { - preprocess: preprocess() -}; diff --git a/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.js b/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.js new file mode 100644 index 000000000000..6bd253bdf27d --- /dev/null +++ b/packages/kit/src/packaging/test/fixtures/resolve-alias/svelte.config.js @@ -0,0 +1,5 @@ +import preprocess from 'svelte-preprocess'; + +export default { + preprocess: preprocess() +}; diff --git a/packages/kit/src/packaging/test/fixtures/typescript/package.json b/packages/kit/src/packaging/test/fixtures/typescript/package.json index 3ead797272b4..a2feaf4d4644 100644 --- a/packages/kit/src/packaging/test/fixtures/typescript/package.json +++ b/packages/kit/src/packaging/test/fixtures/typescript/package.json @@ -1,5 +1,6 @@ { "name": "typescript", "version": "1.0.0", - "description": "standard typescript package" + "description": "standard typescript package", + "type": "module" } diff --git a/packages/kit/src/packaging/test/fixtures/typescript/svelte.config.cjs b/packages/kit/src/packaging/test/fixtures/typescript/svelte.config.cjs deleted file mode 100644 index d0526bbb674d..000000000000 --- a/packages/kit/src/packaging/test/fixtures/typescript/svelte.config.cjs +++ /dev/null @@ -1,5 +0,0 @@ -const preprocess = require('svelte-preprocess'); - -module.exports = { - preprocess: preprocess() -}; diff --git a/packages/kit/src/packaging/test/fixtures/typescript/svelte.config.js b/packages/kit/src/packaging/test/fixtures/typescript/svelte.config.js new file mode 100644 index 000000000000..6bd253bdf27d --- /dev/null +++ b/packages/kit/src/packaging/test/fixtures/typescript/svelte.config.js @@ -0,0 +1,5 @@ +import preprocess from 'svelte-preprocess'; + +export default { + preprocess: preprocess() +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 43f43089e7ee..77c74e1e283d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -258,6 +258,7 @@ importers: sirv: ^1.0.19 svelte: ^3.44.2 svelte-check: ^2.2.10 + svelte-preprocess: ^4.9.8 svelte2tsx: ~0.4.10 tiny-glob: ^0.2.9 uvu: ^0.5.2 @@ -291,6 +292,7 @@ importers: sirv: 1.0.19 svelte: 3.44.2 svelte-check: 2.2.10_svelte@3.44.2 + svelte-preprocess: 4.9.8_svelte@3.44.2+typescript@4.4.4 svelte2tsx: 0.4.10_svelte@3.44.2+typescript@4.4.4 tiny-glob: 0.2.9 uvu: 0.5.2