@sveltejs/vite-plugin-svelte 1.0.0-next.9 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -50
- package/dist/index.cjs +2014 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +231 -214
- package/dist/index.js +1522 -395
- package/dist/index.js.map +1 -0
- package/package.json +48 -33
- package/src/handle-hot-update.ts +117 -0
- package/src/index.ts +242 -0
- package/src/ui/inspector/Inspector.svelte +245 -0
- package/src/ui/inspector/load-inspector.js +15 -0
- package/src/ui/inspector/plugin.ts +106 -0
- package/src/utils/__tests__/dependencies.spec.ts +43 -0
- package/src/utils/__tests__/sourcemap.spec.ts +25 -0
- package/src/utils/compile.ts +159 -0
- package/src/utils/constants.ts +20 -0
- package/src/utils/dependencies.ts +241 -0
- package/src/utils/error.ts +95 -0
- package/src/utils/esbuild.ts +84 -0
- package/src/utils/hash.ts +32 -0
- package/src/utils/id.ts +135 -0
- package/src/utils/load-svelte-config.ts +115 -0
- package/src/utils/log.ts +211 -0
- package/src/utils/optimizer.ts +45 -0
- package/src/utils/options.ts +707 -0
- package/src/utils/preprocess.ts +252 -0
- package/src/utils/resolve.ts +57 -0
- package/src/utils/sourcemap.ts +58 -0
- package/src/utils/vite-plugin-svelte-cache.ts +127 -0
- package/src/utils/watch.ts +110 -0
- package/CHANGELOG.md +0 -44
package/src/utils/id.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import { createFilter } from '@rollup/pluginutils';
|
|
3
|
+
import { Arrayable, ResolvedOptions } from './options';
|
|
4
|
+
import { normalizePath } from 'vite';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
|
|
7
|
+
const VITE_FS_PREFIX = '/@fs/';
|
|
8
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
9
|
+
|
|
10
|
+
export type SvelteQueryTypes = 'style' | 'script';
|
|
11
|
+
|
|
12
|
+
export interface RequestQuery {
|
|
13
|
+
// our own
|
|
14
|
+
svelte?: boolean;
|
|
15
|
+
type?: SvelteQueryTypes;
|
|
16
|
+
// vite specific
|
|
17
|
+
url?: boolean;
|
|
18
|
+
raw?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SvelteRequest {
|
|
22
|
+
id: string;
|
|
23
|
+
cssId: string;
|
|
24
|
+
filename: string;
|
|
25
|
+
normalizedFilename: string;
|
|
26
|
+
query: RequestQuery;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
ssr: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function splitId(id: string) {
|
|
32
|
+
const parts = id.split(`?`, 2);
|
|
33
|
+
const filename = parts[0];
|
|
34
|
+
const rawQuery = parts[1];
|
|
35
|
+
return { filename, rawQuery };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseToSvelteRequest(
|
|
39
|
+
id: string,
|
|
40
|
+
filename: string,
|
|
41
|
+
rawQuery: string,
|
|
42
|
+
root: string,
|
|
43
|
+
timestamp: number,
|
|
44
|
+
ssr: boolean
|
|
45
|
+
): SvelteRequest | undefined {
|
|
46
|
+
const query = parseRequestQuery(rawQuery);
|
|
47
|
+
if (query.url || query.raw) {
|
|
48
|
+
// skip requests with special vite tags
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const normalizedFilename = normalize(filename, root);
|
|
52
|
+
const cssId = createVirtualImportId(filename, root, 'style');
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
id,
|
|
56
|
+
filename,
|
|
57
|
+
normalizedFilename,
|
|
58
|
+
cssId,
|
|
59
|
+
query,
|
|
60
|
+
timestamp,
|
|
61
|
+
ssr
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function createVirtualImportId(filename: string, root: string, type: SvelteQueryTypes) {
|
|
66
|
+
const parts = ['svelte', `type=${type}`];
|
|
67
|
+
if (type === 'style') {
|
|
68
|
+
parts.push('lang.css');
|
|
69
|
+
}
|
|
70
|
+
if (existsInRoot(filename, root)) {
|
|
71
|
+
filename = root + filename;
|
|
72
|
+
} else if (filename.startsWith(VITE_FS_PREFIX)) {
|
|
73
|
+
filename = IS_WINDOWS
|
|
74
|
+
? filename.slice(VITE_FS_PREFIX.length) // remove /@fs/ from /@fs/C:/...
|
|
75
|
+
: filename.slice(VITE_FS_PREFIX.length - 1); // remove /@fs from /@fs/home/user
|
|
76
|
+
}
|
|
77
|
+
// return same virtual id format as vite-plugin-vue eg ...App.svelte?svelte&type=style&lang.css
|
|
78
|
+
return `${filename}?${parts.join('&')}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function parseRequestQuery(rawQuery: string): RequestQuery {
|
|
82
|
+
const query = Object.fromEntries(new URLSearchParams(rawQuery));
|
|
83
|
+
for (const key in query) {
|
|
84
|
+
if (query[key] === '') {
|
|
85
|
+
// @ts-ignore
|
|
86
|
+
query[key] = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return query as RequestQuery;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* posixify and remove root at start
|
|
94
|
+
*
|
|
95
|
+
* @param filename
|
|
96
|
+
* @param normalizedRoot
|
|
97
|
+
*/
|
|
98
|
+
function normalize(filename: string, normalizedRoot: string) {
|
|
99
|
+
return stripRoot(normalizePath(filename), normalizedRoot);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function existsInRoot(filename: string, root: string) {
|
|
103
|
+
if (filename.startsWith(VITE_FS_PREFIX)) {
|
|
104
|
+
return false; // vite already tagged it as out of root
|
|
105
|
+
}
|
|
106
|
+
return fs.existsSync(root + filename);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function stripRoot(normalizedFilename: string, normalizedRoot: string) {
|
|
110
|
+
return normalizedFilename.startsWith(normalizedRoot + '/')
|
|
111
|
+
? normalizedFilename.slice(normalizedRoot.length)
|
|
112
|
+
: normalizedFilename;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function buildFilter(
|
|
116
|
+
include: Arrayable<string> | undefined,
|
|
117
|
+
exclude: Arrayable<string> | undefined,
|
|
118
|
+
extensions: string[]
|
|
119
|
+
): (filename: string) => boolean {
|
|
120
|
+
const rollupFilter = createFilter(include, exclude);
|
|
121
|
+
return (filename) => rollupFilter(filename) && extensions.some((ext) => filename.endsWith(ext));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type IdParser = (id: string, ssr: boolean, timestamp?: number) => SvelteRequest | undefined;
|
|
125
|
+
export function buildIdParser(options: ResolvedOptions): IdParser {
|
|
126
|
+
const { include, exclude, extensions, root } = options;
|
|
127
|
+
const normalizedRoot = normalizePath(root);
|
|
128
|
+
const filter = buildFilter(include, exclude, extensions!);
|
|
129
|
+
return (id, ssr, timestamp = Date.now()) => {
|
|
130
|
+
const { filename, rawQuery } = splitId(id);
|
|
131
|
+
if (filter(filename)) {
|
|
132
|
+
return parseToSvelteRequest(id, filename, rawQuery, normalizedRoot, timestamp, ssr);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { pathToFileURL } from 'url';
|
|
5
|
+
import { log } from './log';
|
|
6
|
+
import { Options, SvelteOptions } from './options';
|
|
7
|
+
import { UserConfig } from 'vite';
|
|
8
|
+
|
|
9
|
+
// used to require cjs config in esm.
|
|
10
|
+
// NOTE dynamic import() cjs technically works, but timestamp query cache bust
|
|
11
|
+
// have no effect, likely because it has another internal cache?
|
|
12
|
+
let esmRequire: NodeRequire;
|
|
13
|
+
|
|
14
|
+
export const knownSvelteConfigNames = [
|
|
15
|
+
'svelte.config.js',
|
|
16
|
+
'svelte.config.cjs',
|
|
17
|
+
'svelte.config.mjs'
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
// hide dynamic import from ts transform to prevent it turning into a require
|
|
21
|
+
// see https://github.com/microsoft/TypeScript/issues/43329#issuecomment-811606238
|
|
22
|
+
// also use timestamp query to avoid caching on reload
|
|
23
|
+
const dynamicImportDefault = new Function(
|
|
24
|
+
'path',
|
|
25
|
+
'timestamp',
|
|
26
|
+
'return import(path + "?t=" + timestamp).then(m => m.default)'
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export async function loadSvelteConfig(
|
|
30
|
+
viteConfig?: UserConfig,
|
|
31
|
+
inlineOptions?: Partial<Options>
|
|
32
|
+
): Promise<Partial<SvelteOptions> | undefined> {
|
|
33
|
+
if (inlineOptions?.configFile === false) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const configFile = findConfigToLoad(viteConfig, inlineOptions);
|
|
37
|
+
if (configFile) {
|
|
38
|
+
let err;
|
|
39
|
+
// try to use dynamic import for svelte.config.js first
|
|
40
|
+
if (configFile.endsWith('.js') || configFile.endsWith('.mjs')) {
|
|
41
|
+
try {
|
|
42
|
+
const result = await dynamicImportDefault(
|
|
43
|
+
pathToFileURL(configFile).href,
|
|
44
|
+
fs.statSync(configFile).mtimeMs
|
|
45
|
+
);
|
|
46
|
+
if (result != null) {
|
|
47
|
+
return {
|
|
48
|
+
...result,
|
|
49
|
+
configFile
|
|
50
|
+
};
|
|
51
|
+
} else {
|
|
52
|
+
throw new Error(`invalid export in ${configFile}`);
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
log.error(`failed to import config ${configFile}`, e);
|
|
56
|
+
err = e;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// cjs or error with dynamic import
|
|
60
|
+
if (!configFile.endsWith('.mjs')) {
|
|
61
|
+
try {
|
|
62
|
+
// identify which require function to use (esm and cjs mode)
|
|
63
|
+
const _require = import.meta.url
|
|
64
|
+
? (esmRequire ??= createRequire(import.meta.url))
|
|
65
|
+
: require;
|
|
66
|
+
|
|
67
|
+
// avoid loading cached version on reload
|
|
68
|
+
delete _require.cache[_require.resolve(configFile)];
|
|
69
|
+
const result = _require(configFile);
|
|
70
|
+
if (result != null) {
|
|
71
|
+
return {
|
|
72
|
+
...result,
|
|
73
|
+
configFile
|
|
74
|
+
};
|
|
75
|
+
} else {
|
|
76
|
+
throw new Error(`invalid export in ${configFile}`);
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
log.error(`failed to require config ${configFile}`, e);
|
|
80
|
+
if (!err) {
|
|
81
|
+
err = e;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// failed to load existing config file
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function findConfigToLoad(viteConfig?: UserConfig, inlineOptions?: Partial<Options>) {
|
|
91
|
+
const root = viteConfig?.root || process.cwd();
|
|
92
|
+
if (inlineOptions?.configFile) {
|
|
93
|
+
const abolutePath = path.isAbsolute(inlineOptions.configFile)
|
|
94
|
+
? inlineOptions.configFile
|
|
95
|
+
: path.resolve(root, inlineOptions.configFile);
|
|
96
|
+
if (!fs.existsSync(abolutePath)) {
|
|
97
|
+
throw new Error(`failed to find svelte config file ${abolutePath}.`);
|
|
98
|
+
}
|
|
99
|
+
return abolutePath;
|
|
100
|
+
} else {
|
|
101
|
+
const existingKnownConfigFiles = knownSvelteConfigNames
|
|
102
|
+
.map((candidate) => path.resolve(root, candidate))
|
|
103
|
+
.filter((file) => fs.existsSync(file));
|
|
104
|
+
if (existingKnownConfigFiles.length === 0) {
|
|
105
|
+
log.debug(`no svelte config found at ${root}`);
|
|
106
|
+
return;
|
|
107
|
+
} else if (existingKnownConfigFiles.length > 1) {
|
|
108
|
+
log.warn(
|
|
109
|
+
`found more than one svelte config file, using ${existingKnownConfigFiles[0]}. you should only have one!`,
|
|
110
|
+
existingKnownConfigFiles
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return existingKnownConfigFiles[0];
|
|
114
|
+
}
|
|
115
|
+
}
|
package/src/utils/log.ts
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars,no-console */
|
|
2
|
+
import { cyan, yellow, red } from 'kleur/colors';
|
|
3
|
+
import debug from 'debug';
|
|
4
|
+
import { ResolvedOptions, Warning } from './options';
|
|
5
|
+
import { SvelteRequest } from './id';
|
|
6
|
+
|
|
7
|
+
const levels: string[] = ['debug', 'info', 'warn', 'error', 'silent'];
|
|
8
|
+
const prefix = 'vite-plugin-svelte';
|
|
9
|
+
const loggers: { [key: string]: any } = {
|
|
10
|
+
debug: {
|
|
11
|
+
log: debug(`vite:${prefix}`),
|
|
12
|
+
enabled: false,
|
|
13
|
+
isDebug: true
|
|
14
|
+
},
|
|
15
|
+
info: {
|
|
16
|
+
color: cyan,
|
|
17
|
+
log: console.log,
|
|
18
|
+
enabled: true
|
|
19
|
+
},
|
|
20
|
+
warn: {
|
|
21
|
+
color: yellow,
|
|
22
|
+
log: console.warn,
|
|
23
|
+
enabled: true
|
|
24
|
+
},
|
|
25
|
+
error: {
|
|
26
|
+
color: red,
|
|
27
|
+
log: console.error,
|
|
28
|
+
enabled: true
|
|
29
|
+
},
|
|
30
|
+
silent: {
|
|
31
|
+
enabled: false
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
let _level: string = 'info';
|
|
36
|
+
function setLevel(level: string) {
|
|
37
|
+
if (level === _level) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const levelIndex = levels.indexOf(level);
|
|
41
|
+
if (levelIndex > -1) {
|
|
42
|
+
_level = level;
|
|
43
|
+
for (let i = 0; i < levels.length; i++) {
|
|
44
|
+
loggers[levels[i]].enabled = i >= levelIndex;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
_log(loggers.error, `invalid log level: ${level} `);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function _log(logger: any, message: string, payload?: any) {
|
|
52
|
+
if (!logger.enabled) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (logger.isDebug) {
|
|
56
|
+
payload !== undefined ? logger.log(message, payload) : logger.log(message);
|
|
57
|
+
} else {
|
|
58
|
+
logger.log(logger.color(`${new Date().toLocaleTimeString()} [${prefix}] ${message}`));
|
|
59
|
+
if (payload) {
|
|
60
|
+
logger.log(payload);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface LogFn {
|
|
66
|
+
(message: string, payload?: any): void;
|
|
67
|
+
enabled: boolean;
|
|
68
|
+
once: (message: string, payload?: any) => void;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function createLogger(level: string): LogFn {
|
|
72
|
+
const logger = loggers[level];
|
|
73
|
+
const logFn: LogFn = _log.bind(null, logger) as LogFn;
|
|
74
|
+
const logged = new Set<String>();
|
|
75
|
+
const once = function (message: string, payload?: any) {
|
|
76
|
+
if (logged.has(message)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
logged.add(message);
|
|
80
|
+
logFn.apply(null, [message, payload]);
|
|
81
|
+
};
|
|
82
|
+
Object.defineProperty(logFn, 'enabled', {
|
|
83
|
+
get() {
|
|
84
|
+
return logger.enabled;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
Object.defineProperty(logFn, 'once', {
|
|
88
|
+
get() {
|
|
89
|
+
return once;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return logFn;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const log = {
|
|
96
|
+
debug: createLogger('debug'),
|
|
97
|
+
info: createLogger('info'),
|
|
98
|
+
warn: createLogger('warn'),
|
|
99
|
+
error: createLogger('error'),
|
|
100
|
+
setLevel
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export type SvelteWarningsMessage = {
|
|
104
|
+
id: string;
|
|
105
|
+
filename: string;
|
|
106
|
+
normalizedFilename: string;
|
|
107
|
+
timestamp: number;
|
|
108
|
+
warnings: Warning[]; // allWarnings filtered by warnings where onwarn did not call the default handler
|
|
109
|
+
allWarnings: Warning[]; // includes warnings filtered by onwarn and our extra vite plugin svelte warnings
|
|
110
|
+
rawWarnings: Warning[]; // raw compiler output
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export function logCompilerWarnings(
|
|
114
|
+
svelteRequest: SvelteRequest,
|
|
115
|
+
warnings: Warning[],
|
|
116
|
+
options: ResolvedOptions
|
|
117
|
+
) {
|
|
118
|
+
const { emitCss, onwarn, isBuild } = options;
|
|
119
|
+
const sendViaWS = !isBuild && options.experimental?.sendWarningsToBrowser;
|
|
120
|
+
let warn = isBuild ? warnBuild : warnDev;
|
|
121
|
+
const handledByDefaultWarn: Warning[] = [];
|
|
122
|
+
const notIgnored = warnings?.filter((w) => !ignoreCompilerWarning(w, isBuild, emitCss));
|
|
123
|
+
const extra = buildExtraWarnings(warnings, isBuild);
|
|
124
|
+
const allWarnings = [...notIgnored, ...extra];
|
|
125
|
+
if (sendViaWS) {
|
|
126
|
+
const _warn = warn;
|
|
127
|
+
warn = (w: Warning) => {
|
|
128
|
+
handledByDefaultWarn.push(w);
|
|
129
|
+
_warn(w);
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
allWarnings.forEach((warning) => {
|
|
133
|
+
if (onwarn) {
|
|
134
|
+
onwarn(warning, warn);
|
|
135
|
+
} else {
|
|
136
|
+
warn(warning);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
if (sendViaWS) {
|
|
140
|
+
const message: SvelteWarningsMessage = {
|
|
141
|
+
id: svelteRequest.id,
|
|
142
|
+
filename: svelteRequest.filename,
|
|
143
|
+
normalizedFilename: svelteRequest.normalizedFilename,
|
|
144
|
+
timestamp: svelteRequest.timestamp,
|
|
145
|
+
warnings: handledByDefaultWarn, // allWarnings filtered by warnings where onwarn did not call the default handler
|
|
146
|
+
allWarnings, // includes warnings filtered by onwarn and our extra vite plugin svelte warnings
|
|
147
|
+
rawWarnings: warnings // raw compiler output
|
|
148
|
+
};
|
|
149
|
+
log.debug(`sending svelte:warnings message for ${svelteRequest.normalizedFilename}`);
|
|
150
|
+
options.server?.ws?.send('svelte:warnings', message);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function ignoreCompilerWarning(
|
|
155
|
+
warning: Warning,
|
|
156
|
+
isBuild: boolean,
|
|
157
|
+
emitCss: boolean | undefined
|
|
158
|
+
): boolean {
|
|
159
|
+
return (
|
|
160
|
+
(!emitCss && warning.code === 'css-unused-selector') || // same as rollup-plugin-svelte
|
|
161
|
+
(!isBuild && isNoScopableElementWarning(warning))
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function isNoScopableElementWarning(warning: Warning) {
|
|
166
|
+
// see https://github.com/sveltejs/vite-plugin-svelte/issues/153
|
|
167
|
+
return warning.code === 'css-unused-selector' && warning.message.includes('"*"');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function buildExtraWarnings(warnings: Warning[], isBuild: boolean): Warning[] {
|
|
171
|
+
const extraWarnings = [];
|
|
172
|
+
if (!isBuild) {
|
|
173
|
+
const noScopableElementWarnings = warnings.filter((w) => isNoScopableElementWarning(w));
|
|
174
|
+
if (noScopableElementWarnings.length > 0) {
|
|
175
|
+
// in case there are multiple, use last one as that is the one caused by our *{} rule
|
|
176
|
+
const noScopableElementWarning =
|
|
177
|
+
noScopableElementWarnings[noScopableElementWarnings.length - 1];
|
|
178
|
+
extraWarnings.push({
|
|
179
|
+
...noScopableElementWarning,
|
|
180
|
+
code: 'vite-plugin-svelte-css-no-scopable-elements',
|
|
181
|
+
message: `No scopable elements found in template. If you're using global styles in the style tag, you should move it into an external stylesheet file and import it in JS. See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#where-should-i-put-my-global-styles.`
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return extraWarnings;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function warnDev(w: Warning) {
|
|
189
|
+
log.info.enabled && log.info(buildExtendedLogMessage(w));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function warnBuild(w: Warning) {
|
|
193
|
+
log.warn.enabled && log.warn(buildExtendedLogMessage(w), w.frame);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function buildExtendedLogMessage(w: Warning) {
|
|
197
|
+
const parts = [];
|
|
198
|
+
if (w.filename) {
|
|
199
|
+
parts.push(w.filename);
|
|
200
|
+
}
|
|
201
|
+
if (w.start) {
|
|
202
|
+
parts.push(':', w.start.line, ':', w.start.column);
|
|
203
|
+
}
|
|
204
|
+
if (w.message) {
|
|
205
|
+
if (parts.length > 0) {
|
|
206
|
+
parts.push(' ');
|
|
207
|
+
}
|
|
208
|
+
parts.push(w.message);
|
|
209
|
+
}
|
|
210
|
+
return parts.join('');
|
|
211
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { ResolvedOptions } from './options';
|
|
4
|
+
|
|
5
|
+
// List of options that changes the prebundling result
|
|
6
|
+
const PREBUNDLE_SENSITIVE_OPTIONS: (keyof ResolvedOptions)[] = [
|
|
7
|
+
'compilerOptions',
|
|
8
|
+
'configFile',
|
|
9
|
+
'experimental',
|
|
10
|
+
'extensions',
|
|
11
|
+
'ignorePluginPreprocessors',
|
|
12
|
+
'preprocess'
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @returns Whether the Svelte metadata has changed
|
|
17
|
+
*/
|
|
18
|
+
export async function saveSvelteMetadata(cacheDir: string, options: ResolvedOptions) {
|
|
19
|
+
const svelteMetadata = generateSvelteMetadata(options);
|
|
20
|
+
const svelteMetadataPath = path.resolve(cacheDir, '_svelte_metadata.json');
|
|
21
|
+
|
|
22
|
+
const currentSvelteMetadata = JSON.stringify(svelteMetadata, (_, value) => {
|
|
23
|
+
// Handle preprocessors
|
|
24
|
+
return typeof value === 'function' ? value.toString() : value;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
let existingSvelteMetadata: string | undefined;
|
|
28
|
+
try {
|
|
29
|
+
existingSvelteMetadata = await fs.readFile(svelteMetadataPath, 'utf8');
|
|
30
|
+
} catch {
|
|
31
|
+
// ignore
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await fs.mkdir(cacheDir, { recursive: true });
|
|
35
|
+
await fs.writeFile(svelteMetadataPath, currentSvelteMetadata);
|
|
36
|
+
return currentSvelteMetadata !== existingSvelteMetadata;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function generateSvelteMetadata(options: ResolvedOptions) {
|
|
40
|
+
const metadata: Record<string, any> = {};
|
|
41
|
+
for (const key of PREBUNDLE_SENSITIVE_OPTIONS) {
|
|
42
|
+
metadata[key] = options[key];
|
|
43
|
+
}
|
|
44
|
+
return metadata;
|
|
45
|
+
}
|