@svitejs/vite-plugin-svelte
Version:
592 lines (580 loc) • 18.9 kB
JavaScript
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;