@@ -9,8 +9,7 @@ import { toESBuildError } from './error.js';
9
9
*/
10
10
11
11
export const facadeEsbuildSveltePluginName = 'vite-plugin-svelte:facade' ;
12
-
13
- const svelteModuleExtension = '.svelte.js' ;
12
+ export const facadeEsbuildSvelteModulePluginName = 'vite-plugin-svelte-module:facade' ;
14
13
15
14
/**
16
15
* @param {import('../types/options.d.ts').ResolvedOptions } options
@@ -24,18 +23,15 @@ export function esbuildSveltePlugin(options) {
24
23
// Otherwise this would heavily slow down the scanning phase.
25
24
if ( build . initialOptions . plugins ?. some ( ( v ) => v . name === 'vite:dep-scan' ) ) return ;
26
25
27
- const svelteExtensions = ( options . extensions ?? [ '.svelte' ] ) . map ( ( ext ) => ext . slice ( 1 ) ) ;
28
- svelteExtensions . push ( svelteModuleExtension . slice ( 1 ) ) ;
29
-
30
- const svelteFilter = new RegExp ( '\\.(' + svelteExtensions . join ( '|' ) + ')(\\?.*)?$' ) ;
26
+ const filter = / \. s v e l t e (?: \? .* ) ? $ / ;
31
27
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined } */
32
28
let statsCollection ;
33
29
build . onStart ( ( ) => {
34
- statsCollection = options . stats ?. startCollection ( 'prebundle libraries ' , {
30
+ statsCollection = options . stats ?. startCollection ( 'prebundle library components ' , {
35
31
logResult : ( c ) => c . stats . length > 1
36
32
} ) ;
37
33
} ) ;
38
- build . onLoad ( { filter : svelteFilter } , async ( { path : filename } ) => {
34
+ build . onLoad ( { filter } , async ( { path : filename } ) => {
39
35
const code = readFileSync ( filename , 'utf8' ) ;
40
36
try {
41
37
const contents = await compileSvelte ( options , { filename, code } , statsCollection ) ;
@@ -58,26 +54,14 @@ export function esbuildSveltePlugin(options) {
58
54
* @returns {Promise<string> }
59
55
*/
60
56
async function compileSvelte ( options , { filename, code } , statsCollection ) {
61
- if ( filename . endsWith ( svelteModuleExtension ) ) {
62
- const endStat = statsCollection ?. start ( filename ) ;
63
- const compiled = svelte . compileModule ( code , {
64
- filename,
65
- generate : 'client'
66
- } ) ;
67
- if ( endStat ) {
68
- endStat ( ) ;
69
- }
70
- return compiled . js . map
71
- ? compiled . js . code + '//# sourceMappingURL=' + compiled . js . map . toUrl ( )
72
- : compiled . js . code ;
73
- }
74
57
let css = options . compilerOptions . css ;
75
58
if ( css !== 'injected' ) {
76
59
// TODO ideally we'd be able to externalize prebundled styles too, but for now always put them in the js
77
60
css = 'injected' ;
78
61
}
79
62
/** @type {import('svelte/compiler').CompileOptions } */
80
63
const compileOptions = {
64
+ dev : true , // default to dev: true because prebundling is only used in dev
81
65
...options . compilerOptions ,
82
66
css,
83
67
filename,
@@ -127,3 +111,60 @@ async function compileSvelte(options, { filename, code }, statsCollection) {
127
111
? compiled . js . code + '//# sourceMappingURL=' + compiled . js . map . toUrl ( )
128
112
: compiled . js . code ;
129
113
}
114
+
115
+ /**
116
+ * @param {import('../types/options.d.ts').ResolvedOptions } options
117
+ * @returns {EsbuildPlugin }
118
+ */
119
+ export function esbuildSvelteModulePlugin ( options ) {
120
+ return {
121
+ name : 'vite-plugin-svelte-module:optimize-svelte' ,
122
+ setup ( build ) {
123
+ // Skip in scanning phase as Vite already handles scanning Svelte files.
124
+ // Otherwise this would heavily slow down the scanning phase.
125
+ if ( build . initialOptions . plugins ?. some ( ( v ) => v . name === 'vite:dep-scan' ) ) return ;
126
+
127
+ const filter = / \. s v e l t e \. [ j t ] s (?: \? .* ) ? $ / ;
128
+ /** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection | undefined } */
129
+ let statsCollection ;
130
+ build . onStart ( ( ) => {
131
+ statsCollection = options . stats ?. startCollection ( 'prebundle library modules' , {
132
+ logResult : ( c ) => c . stats . length > 1
133
+ } ) ;
134
+ } ) ;
135
+ build . onLoad ( { filter } , async ( { path : filename } ) => {
136
+ const code = readFileSync ( filename , 'utf8' ) ;
137
+ try {
138
+ const contents = await compileSvelteModule ( options , { filename, code } , statsCollection ) ;
139
+ return { contents } ;
140
+ } catch ( e ) {
141
+ return { errors : [ toESBuildError ( e , options ) ] } ;
142
+ }
143
+ } ) ;
144
+ build . onEnd ( ( ) => {
145
+ statsCollection ?. finish ( ) ;
146
+ } ) ;
147
+ }
148
+ } ;
149
+ }
150
+
151
+ /**
152
+ * @param {import('../types/options.d.ts').ResolvedOptions } options
153
+ * @param {{ filename: string; code: string } } input
154
+ * @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection } [statsCollection]
155
+ * @returns {Promise<string> }
156
+ */
157
+ async function compileSvelteModule ( options , { filename, code } , statsCollection ) {
158
+ const endStat = statsCollection ?. start ( filename ) ;
159
+ const compiled = svelte . compileModule ( code , {
160
+ dev : options . compilerOptions ?. dev ?? true , // default to dev: true because prebundling is only used in dev
161
+ filename,
162
+ generate : 'client'
163
+ } ) ;
164
+ if ( endStat ) {
165
+ endStat ( ) ;
166
+ }
167
+ return compiled . js . map
168
+ ? compiled . js . code + '//# sourceMappingURL=' + compiled . js . map . toUrl ( )
169
+ : compiled . js . code ;
170
+ }
0 commit comments