@@ -8,144 +8,108 @@ import { viteTsConfigPaths } from '../../vite-extensions/vite-ts-config-paths';
88// eslint-disable-next-line @nx/enforce-module-boundaries
99import { viteIgnoreImports } from '../../vite-extensions/vite-ignore-imports' ;
1010// eslint-disable-next-line @nx/enforce-module-boundaries
11+ import { viteExternalDynamicImports } from '../../vite-extensions/vite-external-dynamic-imports' ;
12+ // eslint-disable-next-line @nx/enforce-module-boundaries
1113import viteGlobalExtensions from '../../vite-extensions/vite-global-extensions' ;
1214// eslint-disable-next-line @nx/enforce-module-boundaries
1315import { getExternalModules } from '../../vite-extensions/vite-external-modules' ;
1416
15- export default defineConfig ( ( { command } ) => {
16- return {
17- cacheDir : '../../../node_modules/.vite/php-wasm' ,
17+ export default defineConfig ( {
18+ cacheDir : '../../../node_modules/.vite/php-wasm' ,
1819
19- plugins : [
20- viteTsConfigPaths ( {
21- root : '../../../' ,
22- } ) ,
23- dts ( {
24- entryRoot : 'src' ,
25- tsconfigPath : path . join ( __dirname , 'tsconfig.lib.json' ) ,
26- pathsToAliases : false ,
27- } ) ,
28- viteIgnoreImports ( {
29- extensions : [ 'wasm' , 'so' , 'dat' ] ,
30- } ) ,
31- /**
32- * Vite can't extract static asset in the library mode:
33- * https://github.com/vitejs/vite/issues/3295
34- *
35- * This workaround replaces the actual php_5_6.js modules paths used
36- * in the dev mode with their filenames. Then, the filenames are marked
37- * as external further down in this config. As a result, the final
38- * bundle contains literal `import('php_5_6.js')` and
39- * `import('php_5_6.wasm')` statements which allows the consumers to use
40- * their own loaders.
41- *
42- * This keeps the dev mode working AND avoids inlining 5mb of
43- * wasm via base64 in the final bundle.
44- */
20+ plugins : [
21+ viteTsConfigPaths ( {
22+ root : '../../../' ,
23+ } ) ,
24+ dts ( {
25+ entryRoot : 'src' ,
26+ tsconfigPath : path . join ( __dirname , 'tsconfig.lib.json' ) ,
27+ pathsToAliases : false ,
28+ } ) ,
29+ viteIgnoreImports ( {
30+ extensions : [ 'wasm' , 'so' , 'dat' ] ,
31+ } ) ,
32+ /*
33+ * These transforms rewrite dynamic import paths so they work from the dist output.
34+ *
35+ * Each transform does two things:
36+ * 1. slice(-N) extracts the path segments we want to keep (strips the 'public' prefix)
37+ * 2. The '../' prefix compensates for the source file's directory depth
38+ *
39+ * Why the '../' prefix? Rollup computes the final import path relative to
40+ * where the source file was located. Since everything gets bundled into
41+ * index.js at the dist root, we need to "climb out" of the source directory
42+ * structure. Rollup then normalizes '../foo' to './foo' in the output.
43+ *
44+ * Example for php_8_4.js:
45+ * Source file: src/lib/get-php-loader-module.ts (2 levels deep: src/lib/)
46+ * Input: '../../public/php/jspi/php_8_4.js'
47+ * slice(-3): 'php/jspi/php_8_4.js'
48+ * With '../': '../php/jspi/php_8_4.js'
49+ * Output: './php/jspi/php_8_4.js' (rollup normalizes for dist root)
50+ */
51+ viteExternalDynamicImports ( [
4552 {
46- name : 'preserve-php-loaders-imports' ,
47-
48- resolveDynamicImport ( specifier ) : string | void {
49- if (
50- command === 'build' &&
51- typeof specifier === 'string' &&
52- specifier . match ( / p h p _ \d _ \d \. j s $ / )
53- ) {
54- /**
55- * The ../ is weird but necessary to make the final build say
56- * import("./php/jspi/php_8_2.js")
57- * and not
58- * import("php/jspi/php_8_2.js")
59- *
60- * The slice(-3) will ensure the 'php/jspi/'
61- * portion of the path is preserved.
62- */
63- return '../' + specifier . split ( '/' ) . slice ( - 3 ) . join ( '/' ) ;
64- }
65- } ,
53+ // Source: src/lib/get-php-loader-module.ts (1 dir from src/)
54+ // Input: '../../public/php/jspi/php_8_4.js'
55+ // slice(-3): 'php/jspi/php_8_4.js'
56+ // With '../': '../php/jspi/php_8_4.js'
57+ // Output: './php/jspi/php_8_4.js'
58+ regex : / p h p _ \d _ \d \. j s $ / ,
59+ transform : ( specifier ) =>
60+ `../${ specifier . split ( '/' ) . slice ( - 3 ) . join ( '/' ) } ` ,
6661 } ,
6762 {
68- name : 'preserve-data-loaders-imports' ,
69-
70- resolveDynamicImport ( specifier ) : string | void {
71- if (
72- command === 'build' &&
73- typeof specifier === 'string' &&
74- specifier . match ( / i c u \. d a t $ / )
75- ) {
76- /**
77- * The ../../../ is weird but necessary to make the final build say
78- * import("./shared/icu.dat")
79- * and not
80- * import("shared/icu.dat")
81- *
82- * The slice(-2) will ensure the 'shared/'
83- * portion of the path is preserved.
84- */
85- return (
86- '../../../' +
87- specifier . split ( '/' ) . slice ( - 2 ) . join ( '/' )
88- ) ;
89- }
90- } ,
63+ // Source: src/lib/extensions/intl/get-intl-extension-module.ts (3 dirs from src/)
64+ // Input: '../../../../public/php/jspi/extensions/intl/8_4/intl.so'
65+ // slice(-6): 'php/jspi/extensions/intl/8_4/intl.so'
66+ // With '../../../': '../../../php/jspi/extensions/intl/8_4/intl.so'
67+ // Output: './php/jspi/extensions/intl/8_4/intl.so'
68+ regex : / i n t l \. s o $ / ,
69+ transform : ( specifier ) =>
70+ `../../../${ specifier . split ( '/' ) . slice ( - 6 ) . join ( '/' ) } ` ,
9171 } ,
9272 {
93- name : 'preserve-extension-loaders-imports' ,
94-
95- resolveDynamicImport ( specifier ) : string | void {
96- if (
97- command === 'build' &&
98- typeof specifier === 'string' &&
99- specifier . match ( / i n t l \. s o $ / )
100- ) {
101- /**
102- * The ../../../ is weird but necessary to make the final build say
103- * import("./php/{mode}/extensions/intl/{php_version}/intl.so")
104- * and not
105- * import("php/{mode}/extensions/intl/{php_version}/intl.so")
106- *
107- * The slice(-6) will ensure the 'php/{mode}/extensions/intl/{php_version}'
108- * portion of the path is preserved.
109- */
110- return (
111- '../../../' +
112- specifier . split ( '/' ) . slice ( - 6 ) . join ( '/' )
113- ) ;
114- }
115- } ,
73+ // Source: src/lib/extensions/intl/with-intl.ts (3 dirs from src/)
74+ // Input: '../../../../public/shared/icu.dat'
75+ // slice(-2): 'shared/icu.dat'
76+ // With '../../../': '../../../shared/icu.dat'
77+ // Output: './shared/icu.dat'
78+ regex : / i c u \. d a t $ / ,
79+ transform : ( specifier ) =>
80+ `../../../${ specifier . split ( '/' ) . slice ( - 2 ) . join ( '/' ) } ` ,
11681 } ,
82+ ] ) ,
83+ ...viteGlobalExtensions ,
84+ ] ,
11785
118- ...viteGlobalExtensions ,
119- ] ,
120-
121- // Configuration for building your library.
122- // See: https://vitejs.dev/guide/build.html#library-mode
123- build : {
124- lib : {
125- // Could also be a dictionary or array of multiple entry points.
126- entry : 'src/index.ts' ,
127- name : 'php-wasm-web' ,
128- fileName : 'index' ,
129- formats : [ 'es' , 'cjs' ] ,
130- } ,
131- sourcemap : true ,
132- rollupOptions : {
133- // Don't bundle the PHP loaders in the final build. See
134- // the preserve-php-loaders-imports plugin above.
135- external : [
136- / p h p _ \d _ \d .j s $ / ,
137- / i c u .d a t $ / ,
138- / i n t l .s o $ / ,
139- ...getExternalModules ( ) ,
140- ] ,
141- } ,
86+ // Configuration for building your library.
87+ // See: https://vitejs.dev/guide/build.html#library-mode
88+ build : {
89+ lib : {
90+ // Could also be a dictionary or array of multiple entry points.
91+ entry : 'src/index.ts' ,
92+ name : 'php-wasm-web' ,
93+ fileName : 'index' ,
94+ formats : [ 'es' , 'cjs' ] ,
14295 } ,
143-
144- // TODO : move Vitest tests to Playwright tests inside test directory
145- test : {
146- globals : true ,
147- environment : 'node' ,
148- reporters : [ 'default' ] ,
96+ sourcemap : true ,
97+ rollupOptions : {
98+ // Don't bundle the PHP loaders in the final build. See
99+ // the viteExternalDynamicImports plugin above.
100+ external : [
101+ / p h p _ \d _ \d .j s $ / ,
102+ / i c u .d a t $ / ,
103+ / i n t l .s o $ / ,
104+ ...getExternalModules ( ) ,
105+ ] ,
149106 } ,
150- } ;
107+ } ,
108+
109+ // TODO : move Vitest tests to Playwright tests inside test directory
110+ test : {
111+ globals : true ,
112+ environment : 'node' ,
113+ reporters : [ 'default' ] ,
114+ } ,
151115} ) ;
0 commit comments