UNPKG

@svitejs/vite-plugin-svelte

Version:
592 lines (580 loc) 18.9 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __markAsModule = (target) => __defProp(target, "__esModule", {value: true}); var __export = (target, all) => { for (var name in all) __defProp(target, name, {get: all[name], enumerable: true}); }; var __exportStar = (target, module2, desc) => { if (module2 && typeof module2 === "object" || typeof module2 === "function") { for (let key of __getOwnPropNames(module2)) if (!__hasOwnProp.call(target, key) && key !== "default") __defProp(target, key, {get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable}); } return target; }; var __toModule = (module2) => { return __exportStar(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? {get: () => module2.default, enumerable: true} : {value: module2, enumerable: true})), module2); }; // src/index.ts __markAsModule(exports); __export(exports, { default: () => vitePluginSvelte }); var path2 = __toModule(require("path")); var relative = __toModule(require("require-relative")); // src/utils/log.ts var import_chalk = __toModule(require("chalk")); var import_debug = __toModule(require("debug")); var levels = ["debug", "info", "warn", "error", "silent"]; var prefix = "vite-plugin-svelte"; var loggers = { debug: { log: (0, import_debug.default)(`vite:${prefix}`), enabled: false, isDebug: true }, info: { color: import_chalk.default.cyan, log: console.log, enabled: true }, warn: { color: import_chalk.default.yellow, log: console.warn, enabled: true }, error: { color: import_chalk.default.red, log: console.error, enabled: true }, silent: { enabled: false } }; var _level = "info"; function setLevel(level) { if (level === _level) { return; } const levelIndex = levels.indexOf(level); if (levelIndex > -1) { _level = level; for (let i = 0; i < levels.length; i++) { loggers[levels[i]].enabled = i >= levelIndex; } } else { _log(loggers.error, `invalid log level: ${level} `); } } var _viteLogOverwriteProtection = false; function setViteLogOverwriteProtection(viteLogOverwriteProtection) { _viteLogOverwriteProtection = viteLogOverwriteProtection; } function _log(logger, message, payload) { if (!logger.enabled) { return; } if (logger.isDebug) { payload !== void 0 ? logger.log(message, payload) : logger.log(message); } else { logger.log(logger.color(`[${prefix}] ${message}`)); if (payload) { logger.log(payload); } } if (_viteLogOverwriteProtection) { logger.log(""); } } function createLogger(level) { const logger = loggers[level]; const logFn = _log.bind(null, logger); Object.defineProperty(logFn, "enabled", { get() { return logger.enabled; } }); return logFn; } var log = { debug: createLogger("debug"), info: createLogger("info"), warn: createLogger("warn"), error: createLogger("error"), setLevel, setViteLogOverwriteProtection }; // src/handleHotUpdate.ts async function handleHotUpdate(compileSvelte, ctx, svelteRequest, cache) { const {read, server} = ctx; const cachedCompileData = cache.getCompileData(svelteRequest, false); if (!cachedCompileData) { log.debug(`handleHotUpdate first call ${svelteRequest.id}`); return; } const content = await read(); const compileData = await compileSvelte(svelteRequest, content, cachedCompileData.options); cache.setCompileData(compileData); const affectedModules = new Set(); const cssModule = server.moduleGraph.getModuleById(svelteRequest.cssId); const mainModule = server.moduleGraph.getModuleById(svelteRequest.id); if (cssModule && cssChanged(cachedCompileData, compileData)) { log.debug("handleHotUpdate css changed"); affectedModules.add(cssModule); } if (mainModule && jsChanged(cachedCompileData, compileData)) { log.debug("handleHotUpdate js changed"); affectedModules.add(mainModule); } const result = [...affectedModules].filter(Boolean); log.debug(`handleHotUpdate result for ${svelteRequest.id}`, result); const ssrModulesToInvalidate = result.filter((m) => !!m.ssrTransformResult); if (ssrModulesToInvalidate.length > 0) { log.debug(`invalidating modules ${ssrModulesToInvalidate.map((m) => m.id).join(", ")}`); ssrModulesToInvalidate.forEach((moduleNode) => server.moduleGraph.invalidateModule(moduleNode)); } return result; } function cssChanged(prev, next) { return !isCodeEqual(prev.compiled.css, next.compiled.css); } function jsChanged(prev, next) { return !isCodeEqual(prev.compiled.js, next.compiled.js); } function isCodeEqual(a, b) { if (a === b) { return true; } if (a == null && b == null) { return true; } if (a == null || b == null) { return false; } return a.code === b.code; } // src/utils/compile.ts var import_compiler = __toModule(require("svelte/compiler")); var import_svelte_hmr = __toModule(require("svelte-hmr")); // src/utils/hash.ts var crypto = __toModule(require("crypto")); var hashes = Object.create(null); var hash_length = 12; function safeBase64Hash(input) { if (hashes[input]) { return hashes[input]; } const md5 = crypto.createHash("md5"); md5.update(input); const hash = toSafe(md5.digest("base64")).substr(0, hash_length); hashes[input] = hash; return hash; } var replacements = { "+": "-", "/": "_", "=": "" }; var replaceRE = new RegExp(`[${Object.keys(replacements).join("")}]`, "g"); function toSafe(base64) { return base64.replace(replaceRE, (x) => replacements[x]); } // src/utils/compile.ts var _createCompileSvelte = (makeHot) => async function compileSvelte(svelteRequest, code, options) { const {filename, normalizedFilename, cssId, ssr} = svelteRequest; const {onwarn, emitCss = true} = options; const dependencies = []; const finalCompilerOptions = { ...options.compilerOptions, filename, generate: ssr ? "ssr" : "dom", css: !emitCss, hydratable: true }; if (options.hot) { const hash = `s-${safeBase64Hash(cssId)}`; log.debug(`setting cssHash ${hash} for ${cssId}`); finalCompilerOptions.cssHash = () => hash; } let preprocessed; if (options.preprocess) { preprocessed = await (0, import_compiler.preprocess)(code, options.preprocess, {filename}); if (preprocessed.dependencies) dependencies.push(...preprocessed.dependencies); if (preprocessed.map) finalCompilerOptions.sourcemap = preprocessed.map; } const compiled = (0, import_compiler.compile)(preprocessed ? preprocessed.code : code, finalCompilerOptions); (compiled.warnings || []).forEach((warning) => { if (!emitCss && warning.code === "css-unused-selector") return; if (onwarn) onwarn(warning); }); if (emitCss && compiled.css.code) { compiled.js.code += ` import ${JSON.stringify(svelteRequest.cssId)}; `; } if (!ssr && makeHot) { compiled.js.code = makeHot({ id: filename, compiledCode: compiled.js.code, hotOptions: options.hot, compiled, originalCode: code, compileOptions: finalCompilerOptions }); } compiled.js.dependencies = dependencies; const result = { filename, normalizedFilename, cssId, code, preprocessed, compiled, compilerOptions: finalCompilerOptions, options, ssr }; return result; }; function createCompileSvelte({hot = false, hotApi = "", adapter = ""}) { const makeHot = hot && (0, import_svelte_hmr.createMakeHot)({walk: import_compiler.walk, hotApi, adapter}); return _createCompileSvelte(makeHot); } // src/utils/id.ts var import_querystring = __toModule(require("querystring")); var import_pluginutils = __toModule(require("@rollup/pluginutils")); var viteVirtualIdPrefix = "/@id/"; function parseToSvelteRequest(id, root, timestamp, ssr) { const parts = id.split(`?`, 2); let filename = parts[0]; const rawQuery = parts[1]; const query = import_querystring.default.parse(rawQuery); if (query.svelte != null) { query.svelte = true; } if (query.svelte) { filename = stripVirtualImportId(filename, query.type); } const normalizedFilename = normalizePath(filename, root); const cssId = createVirtualImportId(normalizedFilename, "style", timestamp); return { id, cssId, filename, normalizedFilename, query, timestamp, ssr }; } function stripVirtualImportId(filename, type) { if (filename.startsWith(viteVirtualIdPrefix)) { filename = filename.substring(viteVirtualIdPrefix.length); } if (type === "style" && filename.endsWith(".css")) { filename = filename.slice(0, -4); } return filename; } function createVirtualImportId(id, type, timestamp) { if (type === "style") { id = `${id}.css`; } return `${id}?svelte&type=${type}`; } function normalizePath(filename, root) { return filename.startsWith(root + "/") ? filename.replace(root, "") : filename; } function buildFilter(include, exclude, extensions) { const rollupFilter = (0, import_pluginutils.createFilter)(include, exclude); return (svelteRequest) => { var _a; return ((_a = svelteRequest.query) == null ? void 0 : _a.svelte) || rollupFilter(svelteRequest.filename) && extensions.some((ext) => svelteRequest.filename.endsWith(ext)); }; } function buildIdParser(options) { const {include, exclude, extensions, root} = options; const filter = buildFilter(include, exclude, extensions); return (id, ssr, timestamp = Date.now()) => { const svelteRequest = parseToSvelteRequest(id, root, timestamp, ssr); if (filter(svelteRequest)) { return svelteRequest; } }; } // src/utils/loadSvelteConfig.ts var import_path = __toModule(require("path")); var import_fs = __toModule(require("fs")); var knownSvelteConfigNames = ["svelte.config.js", "svelte.config.cjs"]; function loadSvelteConfig(root = process.cwd()) { const foundConfigs = knownSvelteConfigNames.map((candidate) => import_path.default.resolve(root, candidate)).filter((file) => import_fs.default.existsSync(file)); if (foundConfigs.length === 0) { log.warn(`no svelte config found at ${root}`); return; } else if (foundConfigs.length > 1) { log.warn(`found more than one svelte config file, using ${foundConfigs[0]}. you should only have one!`, foundConfigs); } try { const config = require(foundConfigs[0]); return config; } catch (e) { log.error(`failed to load config ${foundConfigs[0]}`, e); } } // src/utils/options.ts var defaultOptions = { extensions: [".svelte"], emitCss: true, compilerOptions: { css: false } }; var knownOptions = new Set([ "include", "exclude", "extensions", "emitCss", "compilerOptions", "preprocess", "hot", "disableTransformCache", "disableCssHmr" ]); function buildInitialOptions(rawOptions) { const options = { ...defaultOptions, ...rawOptions }; const compilerOptions = options.compilerOptions; compilerOptions.format = "esm"; const invalidKeys = Object.keys(rawOptions || {}).filter((key) => !knownOptions.has(key)); if (invalidKeys.length) { log.warn(`invalid plugin options "${invalidKeys.join(", ")}" in config`, rawOptions); } return options; } function resolveOptions(options, config) { const svelteConfig = loadSvelteConfig(config.root); const resolvedOptions = { ...svelteConfig, ...options, root: config.root, isProduction: config.isProduction, isBuild: config.command === "build", isServe: config.command === "serve" }; const compilerOptions = resolvedOptions.compilerOptions; if (config.isProduction) { resolvedOptions.hot = false; resolvedOptions.emitCss = true; compilerOptions.dev = false; } if (resolvedOptions.hot) { compilerOptions.dev = true; resolvedOptions.hot = { ...resolvedOptions.hot, injectCss: !resolvedOptions.emitCss }; } else { compilerOptions.dev = !config.isProduction; } compilerOptions.css = !resolvedOptions.emitCss; log.debug("resolved options", resolvedOptions); return resolvedOptions; } // src/utils/VitePluginSvelteCache.ts var VitePluginSvelteCache = class { constructor() { this._compile = new Map(); this._compileSSR = new Map(); } selectCache(ssr) { return ssr ? this._compileSSR : this._compile; } getCompileData(svelteRequest, errorOnMissing = true) { const cache = this.selectCache(svelteRequest.ssr); const id = svelteRequest.normalizedFilename; if (cache.has(id)) { return cache.get(id); } if (errorOnMissing) { throw new Error(`${id} has no corresponding entry in the ${svelteRequest.ssr ? "ssr" : ""}cache. This is a @svitejs/vite-plugin-svelte internal error, please open an issue.`); } } setCompileData(compileData) { const cache = this.selectCache(!!compileData.ssr); const id = compileData.normalizedFilename; cache.set(id, compileData); } }; // src/index.ts var svelte_packages = [ "svelte/animate", "svelte/easing", "svelte/internal", "svelte/motion", "svelte/store", "svelte/transition", "svelte", "svelte-hmr/runtime/hot-api-esm.js", "svelte-hmr/runtime/proxy-adapter-dom.js", "svelte-hmr" ]; var pkg_export_errors = new Set(); function vitePluginSvelte(rawOptions) { if (process.env.DEBUG != null) { log.setLevel("debug"); } const cache = new VitePluginSvelteCache(); const initialOptions = buildInitialOptions(rawOptions); let requestParser; let options = { isProduction: process.env.NODE_ENV === "production", ...initialOptions, root: process.cwd() }; let server; let compileSvelte; return { name: "vite-plugin-svelte", enforce: "pre", config(config, {mode, command}) { var _a, _b; if (process.env.DEBUG) { log.setLevel("debug"); } else if (config.logLevel) { log.setLevel(config.logLevel); } compileSvelte = createCompileSvelte({ hot: options.hot !== false && mode === "development" && command === "serve", hotApi: (_a = options == null ? void 0 : options.hot) == null ? void 0 : _a.hotApi, adapter: (_b = options == null ? void 0 : options.hot) == null ? void 0 : _b.adapter }); return { optimizeDeps: { exclude: [...svelte_packages] }, resolve: { mainFields: ["svelte"], dedupe: [...svelte_packages] } }; }, configResolved(config) { options = resolveOptions(options, config); requestParser = buildIdParser(options); }, configureServer(_server) { server = _server; }, load(id, ssr) { var _a; const svelteRequest = requestParser(id, !!ssr); if (!svelteRequest) { return; } log.debug("load", svelteRequest); const {filename, query} = svelteRequest; if (query.svelte) { if (query.type === "style") { const compileData = cache.getCompileData(svelteRequest, false); if ((_a = compileData == null ? void 0 : compileData.compiled) == null ? void 0 : _a.css) { log.debug(`load returns css for ${filename}`); return compileData.compiled.css; } } } }, async resolveId(importee, importer, options2, ssr) { const svelteRequest = requestParser(importee, !!ssr); log.debug("resolveId", svelteRequest || importee); if (svelteRequest == null ? void 0 : svelteRequest.query.svelte) { log.debug(`resolveId resolved ${importee}`); return importee; } if (!importer || importee[0] === "." || importee[0] === "\0" || path2.isAbsolute(importee)) { return null; } const parts = importee.split("/"); let dir, pkg, name = parts.shift(); if (name && name[0] === "@") { name += `/${parts.shift()}`; } try { const file = `${name}/package.json`; const resolved = relative.resolve(file, path2.dirname(importer)); dir = path2.dirname(resolved); pkg = require(resolved); } catch (err) { if (err.code === "MODULE_NOT_FOUND") return null; if (err.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") { pkg_export_errors.add(name); return null; } throw err; } if (parts.length === 0 && pkg.svelte) { return path2.resolve(dir, pkg.svelte); } log.debug(`resolveId did not resolve ${importee}`); }, async transform(code, id, ssr) { var _a; const svelteRequest = requestParser(id, !!ssr); if (!svelteRequest) { return; } log.debug("transform", svelteRequest); const {filename, query} = svelteRequest; const cachedCompileData = cache.getCompileData(svelteRequest, false); if (query.svelte) { if (query.type === "style" && ((_a = cachedCompileData == null ? void 0 : cachedCompileData.compiled) == null ? void 0 : _a.css)) { log.debug(`transform returns css for ${filename}`); return cachedCompileData.compiled.css; } log.error("failed to transform tagged svelte request", svelteRequest); throw new Error(`failed to transform tagged svelte request for id ${id}`); } if (cachedCompileData && !options.disableTransformCache) { log.debug(`transform returns cached js for ${filename}`); return cachedCompileData.compiled.js; } const compileData = await compileSvelte(svelteRequest, code, options); cache.setCompileData(compileData); log.debug(`transform returns compiled js for ${filename}`); return compileData.compiled.js; }, handleHotUpdate(ctx) { if (!options.emitCss || options.disableCssHmr) { return; } const svelteRequest = requestParser(ctx.file, false, ctx.timestamp); if (!svelteRequest) { return; } log.debug("handleHotUpdate", svelteRequest); return handleHotUpdate(compileSvelte, ctx, svelteRequest, cache); }, transformIndexHtml(html, ctx) { log.debug("transformIndexHtml", html); }, buildEnd() { if (pkg_export_errors.size > 0) { log.warn(`The following packages did not export their \`package.json\` file so we could not check the "svelte" field.If you had difficulties importing svelte components from a package, then please contact the author and ask them to export the package.json file.`, Array.from(pkg_export_errors, (s) => `- ${s}`).join("\n")); } } }; } module.exports = vitePluginSvelte; vitePluginSvelte["default"] = vitePluginSvelte;