diff --git a/.changeset/nice-tires-stare.md b/.changeset/nice-tires-stare.md new file mode 100644 index 0000000..99db733 --- /dev/null +++ b/.changeset/nice-tires-stare.md @@ -0,0 +1,5 @@ +--- +"@marko/vite": patch +--- + +Fix handling of commonjs dependencies in dev mode SSR diff --git a/package-lock.json b/package-lock.json index 590013c..846da3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,15 @@ "version": "6.0.2", "license": "MIT", "dependencies": { - "@chialab/cjs-to-esm": "^0.19.1", "anymatch": "^3.1.3", + "cjs-module-lexer": "^2.2.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", + "es-module-lexer": "^2.0.0", "fast-glob": "^3.3.3", "htmljs-parser": "^5.10.2", "htmlparser2": "^10.1.0", + "magic-string": "^0.30.21", "relative-import-path": "^1.0.0", "resolve": "^1.22.11", "resolve.exports": "^2.0.3" @@ -689,34 +691,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/@chialab/cjs-to-esm": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@chialab/cjs-to-esm/-/cjs-to-esm-0.19.1.tgz", - "integrity": "sha512-8ql5DjzooYUQqoGqMt/ZpSNarhZzYkmkyXCSx5JQzRFJr562ckUIiivzJOsggZ93YIC1FOFEqJRt8GqSURS0+g==", - "license": "MIT", - "dependencies": { - "@chialab/estransform": "^0.19.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@chialab/estransform": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@chialab/estransform/-/estransform-0.19.1.tgz", - "integrity": "sha512-Op0TvQxnzdcnBriFUIjgg3V3MpOB9Cfs4S7TvIuypPegFOSvuFAOcPl5V02NJ9dyGoOc8W6ORbSldc5PYKhOCQ==", - "license": "MIT", - "dependencies": { - "@napi-rs/magic-string": "^0.3.4", - "@parcel/source-map": "^2.0.0", - "cjs-module-lexer": "^1.2.2", - "es-module-lexer": "^1.0.0", - "oxc-parser": "^0.8.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@csstools/color-helpers": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", @@ -1818,7 +1792,6 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -2273,238 +2246,6 @@ "node": ">=18" } }, - "node_modules/@napi-rs/magic-string": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string/-/magic-string-0.3.4.tgz", - "integrity": "sha512-DEWl/B99RQsyMT3F9bvrXuhL01/eIQp/dtNSE3G1jQ4mTGRcP4iHWxoPZ577WrbjUinrNgvRA5+08g8fkPgimQ==", - "license": "MIT", - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@napi-rs/magic-string-android-arm-eabi": "0.3.4", - "@napi-rs/magic-string-android-arm64": "0.3.4", - "@napi-rs/magic-string-darwin-arm64": "0.3.4", - "@napi-rs/magic-string-darwin-x64": "0.3.4", - "@napi-rs/magic-string-freebsd-x64": "0.3.4", - "@napi-rs/magic-string-linux-arm-gnueabihf": "0.3.4", - "@napi-rs/magic-string-linux-arm64-gnu": "0.3.4", - "@napi-rs/magic-string-linux-arm64-musl": "0.3.4", - "@napi-rs/magic-string-linux-x64-gnu": "0.3.4", - "@napi-rs/magic-string-linux-x64-musl": "0.3.4", - "@napi-rs/magic-string-win32-arm64-msvc": "0.3.4", - "@napi-rs/magic-string-win32-ia32-msvc": "0.3.4", - "@napi-rs/magic-string-win32-x64-msvc": "0.3.4" - } - }, - "node_modules/@napi-rs/magic-string-android-arm-eabi": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-android-arm-eabi/-/magic-string-android-arm-eabi-0.3.4.tgz", - "integrity": "sha512-sszAYxqtzzJ4FDerDNHcqL9NhqPhj8W4DNiOanXYy50mA5oojlRtaAFPiB5ZMrWDBM32v5Q30LrmxQ4eTtu2Dg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-android-arm64": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-android-arm64/-/magic-string-android-arm64-0.3.4.tgz", - "integrity": "sha512-jdQ6HuO0X5rkX4MauTcWR4HWdgjakTOmmzqXg8L26+jOHVVG1LZE+Su5qvV4bP8vMb2h+vPE+JsnwqSmWymu3Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-darwin-arm64": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-darwin-arm64/-/magic-string-darwin-arm64-0.3.4.tgz", - "integrity": "sha512-6NmMtvURce9/oq09XBZmuIeI6lPLGtEJ2ZPO/QzL3nLZa6wygiCnO/sFACKYNg5/73ET5HMMTeuogE1JI+r2Lw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-darwin-x64": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-darwin-x64/-/magic-string-darwin-x64-0.3.4.tgz", - "integrity": "sha512-f9LmfMiUAKDOtl0meOuLYeVb6OERrgGzrTg1Tn3R3fTAShM2kxRbfAuPE9ljuXxIFzOv/uqRNLSl/LqCJwpREA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-freebsd-x64": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-freebsd-x64/-/magic-string-freebsd-x64-0.3.4.tgz", - "integrity": "sha512-rqduQ4odiDK4QdM45xHWRTU4wtFIfpp8g8QGpz+3qqg7ivldDqbbNOrBaf6Oeu77uuEvWggnkyuChotfKgJdJQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-linux-arm-gnueabihf": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-linux-arm-gnueabihf/-/magic-string-linux-arm-gnueabihf-0.3.4.tgz", - "integrity": "sha512-pVaJEdEpiPqIfq3M4+yMAATS7Z9muDcWYn8H7GFH1ygh8GwgLgKfy/n/lG2M6zp18Mwd0x7E2E/qg9GgCyUzoQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-linux-arm64-gnu": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-linux-arm64-gnu/-/magic-string-linux-arm64-gnu-0.3.4.tgz", - "integrity": "sha512-9FwoAih/0tzEZx0BjYYIxWkSRMjonIn91RFM3q3MBs/evmThXUYXUqLNa1PPIkK1JoksswtDi48qWWLt8nGflQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-linux-arm64-musl": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-linux-arm64-musl/-/magic-string-linux-arm64-musl-0.3.4.tgz", - "integrity": "sha512-wCR7R+WPOcAKmVQc1s6h6HwfwW1vL9pM8BjUY9Ljkdb8wt1LmZEmV2Sgfc1SfbRQzbyl+pKeufP6adRRQVzYDA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-linux-x64-gnu": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-linux-x64-gnu/-/magic-string-linux-x64-gnu-0.3.4.tgz", - "integrity": "sha512-sbxFDpYnt5WFbxQ1xozwOvh5A7IftqSI0WnE9O7KsQIOi0ej2dvFbfOW4tmFkvH/YP8KJELo5AhP2+kEq1DpYA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-linux-x64-musl": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-linux-x64-musl/-/magic-string-linux-x64-musl-0.3.4.tgz", - "integrity": "sha512-jN4h/7e2Ul8v3UK5IZu38NXLMdzVWhY4uEDlnwuUAhwRh26wBQ1/pLD97Uy/Z3dFNBQPcsv60XS9fOM1YDNT6w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-win32-arm64-msvc": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-win32-arm64-msvc/-/magic-string-win32-arm64-msvc-0.3.4.tgz", - "integrity": "sha512-gMUyTRHLWpzX2ntJFCbW2Gnla9Y/WUmbkZuW5SBAo/Jo8QojHn76Y4PNgnoXdzcsV9b/45RBxurYKAfFg9WTyg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-win32-ia32-msvc": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-win32-ia32-msvc/-/magic-string-win32-ia32-msvc-0.3.4.tgz", - "integrity": "sha512-QIMauMOvEHgL00K9np/c9CT/CRtLOz3mRTQqcZ9XGzSoAMrpxH71KSpDJrKl7h7Ro6TZ+hJ0C3T+JVuTCZNv4A==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/magic-string-win32-x64-msvc": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@napi-rs/magic-string-win32-x64-msvc/-/magic-string-win32-x64-msvc-0.3.4.tgz", - "integrity": "sha512-V8FMSf828MzOI3P6/765MR7zHU6CUZqiyPhmAnwYoKFNxfv7oCviN/G6NcENeCdcYOvNgh5fYzaNLB96ndId5A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", @@ -2557,110 +2298,6 @@ "node": ">= 8" } }, - "node_modules/@oxc-parser/binding-darwin-arm64": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.8.0.tgz", - "integrity": "sha512-3Dws5Wzj9efojjqvhS4ZF+Abh0EoiI5ciOE2kdLifMzSg4fnmYAIOktoUnPEo87TNIb4SiFJ5JgPBgEyq42Eow==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@oxc-parser/binding-darwin-x64": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.8.0.tgz", - "integrity": "sha512-DAUJ/mfq0Jn2VDYn69bhHTsIWj+aZ/viamexFwaLL7ntkIFmGpzAJZUlWofpY1IRJynKWW+P5AOLYXMllw4qUw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@oxc-parser/binding-linux-arm64-gnu": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.8.0.tgz", - "integrity": "sha512-ZHQVey/O4K3zTIKtpfsbtJIE8MPTRHRxgY3dejaoeFQGf9C3HasgF132Yp4zN/jOUx+x8czKPVa/Af40ViyhGQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-parser/binding-linux-arm64-musl": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.8.0.tgz", - "integrity": "sha512-Diw+Tnf5v+zAYXzDoSKCZsMaroU6GoqZMS7smfDtFnZYTHWZrsTmPBLUQe7AFiG7O7tkhsCdcWjOYgbVkrSVOA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-parser/binding-linux-x64-gnu": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.8.0.tgz", - "integrity": "sha512-WloqcRrtQUVEP/Sy8ZeEgF0HgBKQjOv3zLFZqbC5ipkerKriGcVbsq3fOIMOi/55AM6/UhIAjeZGnoeco72JjQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-parser/binding-linux-x64-musl": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.8.0.tgz", - "integrity": "sha512-2j7BD9szwSXTvSj0Q8VE98UHGYvrgZzdLy4EyB0FilhQnopEfz+YV674rWGY2Il1VYxHJwGctrTJHvARolu37g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-parser/binding-win32-arm64-msvc": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.8.0.tgz", - "integrity": "sha512-mcomr1og17yCmnwn8Q7CRzrH9Va0HccWe4Ld3/u/elBsw0SEzYGVvECRzCyRglYAbKTtusz7as9Jee0RiMOMmg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@oxc-parser/binding-win32-x64-msvc": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.8.0.tgz", - "integrity": "sha512-nIBkc1KZOVYUaHT3+U+gM354P3byMAIXMvlmLMbs0kWVRcI4vrzL8qwWpC6QdBQxWKZGqPEqGolv8H4dDYA9nQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@oxc-project/runtime": { "version": "0.115.0", "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.115.0.tgz", @@ -2681,18 +2318,6 @@ "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@parcel/source-map": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", - "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", - "license": "MIT", - "dependencies": { - "detect-libc": "^1.0.3" - }, - "engines": { - "node": "^12.18.3 || >=14" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -3940,9 +3565,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", "license": "MIT" }, "node_modules/clean-stack": { @@ -4342,18 +3967,6 @@ "node": ">=8" } }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "license": "Apache-2.0", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/detect-newline": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", @@ -4569,9 +4182,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "license": "MIT" }, "node_modules/es6-error": { @@ -6853,7 +6466,6 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -7673,25 +7285,6 @@ "dev": true, "license": "MIT" }, - "node_modules/oxc-parser": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.8.0.tgz", - "integrity": "sha512-ObPeMkbDX7igb7NyyAC8CbVC3fY+YmlMsxsRQ2oyFBkpQtI5tjoyqSDKbS9A9EcJvt2q89C4UoC+HjVBdLYYJg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - }, - "optionalDependencies": { - "@oxc-parser/binding-darwin-arm64": "0.8.0", - "@oxc-parser/binding-darwin-x64": "0.8.0", - "@oxc-parser/binding-linux-arm64-gnu": "0.8.0", - "@oxc-parser/binding-linux-arm64-musl": "0.8.0", - "@oxc-parser/binding-linux-x64-gnu": "0.8.0", - "@oxc-parser/binding-linux-x64-musl": "0.8.0", - "@oxc-parser/binding-win32-arm64-msvc": "0.8.0", - "@oxc-parser/binding-win32-x64-msvc": "0.8.0" - } - }, "node_modules/p-filter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", diff --git a/package.json b/package.json index 7d27475..b64236d 100644 --- a/package.json +++ b/package.json @@ -41,13 +41,15 @@ "version": "changeset version && npm i --package-lock-only" }, "dependencies": { - "@chialab/cjs-to-esm": "^0.19.1", "anymatch": "^3.1.3", + "cjs-module-lexer": "^2.2.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", + "es-module-lexer": "^2.0.0", "fast-glob": "^3.3.3", "htmljs-parser": "^5.10.2", "htmlparser2": "^10.1.0", + "magic-string": "^0.30.21", "relative-import-path": "^1.0.0", "resolve": "^1.22.11", "resolve.exports": "^2.0.3" diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/__snapshots__/build.expected.md b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/__snapshots__/build.expected.md new file mode 100644 index 0000000..1dc8ce5 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/__snapshots__/build.expected.md @@ -0,0 +1,8 @@ +# Loading + +```html +

+ thing via dep +

+``` + diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/__snapshots__/dev.expected.md b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/__snapshots__/dev.expected.md new file mode 100644 index 0000000..1dc8ce5 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/__snapshots__/dev.expected.md @@ -0,0 +1,8 @@ +# Loading + +```html +

+ thing via dep +

+``` + diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/dev-server.mjs b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/dev-server.mjs new file mode 100644 index 0000000..25bc591 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/dev-server.mjs @@ -0,0 +1,43 @@ +// In dev we'll start a Vite dev server in middleware mode, +// and forward requests to our http request handler. + +import { createRequire } from "module"; +import path from "path"; +import url from "url"; +import { createServer } from "vite"; + +// change to import once marko-vite is updated to ESM +const markoPlugin = createRequire(import.meta.url)("../../..").default; + +const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); + +const devServer = await createServer({ + root: __dirname, + appType: "custom", + logLevel: "warn", + plugins: [markoPlugin()], + optimizeDeps: { force: true }, + server: { + ws: false, + hmr: false, + middlewareMode: true, + watch: { + ignored: ["**/node_modules/**", "**/dist/**", "**/__snapshots__/**"], + }, + }, + build: { + assetsInlineLimit: 0, + }, +}); + +export default devServer.middlewares.use(async (req, res, next) => { + try { + const { handler } = await devServer.ssrLoadModule( + path.join(__dirname, "./src/index.js") + ); + await handler(req, res, next); + } catch (err) { + devServer.ssrFixStacktrace(err); + return next(err); + } +}); diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/dep/index.js b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/dep/index.js new file mode 100644 index 0000000..943a002 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/dep/index.js @@ -0,0 +1,3 @@ +const mod = require('transient-dep'); + +exports.thing = () => mod() + ' via dep'; \ No newline at end of file diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/dep/package.json b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/dep/package.json new file mode 100644 index 0000000..4a52bc4 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/dep/package.json @@ -0,0 +1,8 @@ +{ + "name": "dep", + "type": "commonjs", + "main": "./index.js", + "dependencies": { + "transient-dep": "0.0.0" + } +} \ No newline at end of file diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/transient-dep/index.js b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/transient-dep/index.js new file mode 100644 index 0000000..9f23867 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/transient-dep/index.js @@ -0,0 +1 @@ +module.exports = () => 'thing'; diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/transient-dep/package.json b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/transient-dep/package.json new file mode 100644 index 0000000..fabaa4b --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/node_modules/transient-dep/package.json @@ -0,0 +1,5 @@ +{ + "name": "transient-dep", + "type": "commonjs", + "main": "./index.js" +} diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/package.json b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/package.json new file mode 100644 index 0000000..a67b3d9 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/package.json @@ -0,0 +1,6 @@ +{ + "name": "isomorphic-commonjs-module-exports", + "dependencies": { + "dep": "0.0.0" + } +} diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/server.mjs b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/server.mjs new file mode 100644 index 0000000..0df9edf --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/server.mjs @@ -0,0 +1,16 @@ +// In production, simply start up the http server. +import { createServer } from "http"; +import path from 'path' +import serve from "serve-handler"; +import url from 'url'; + +import { handler } from "./dist/index.mjs"; + +const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); +const serveOpts = { public: path.resolve(__dirname, "dist") }; + +export default createServer(async (req, res) => { + await handler(req, res); + if (res.headersSent) return; + await serve(req, res, serveOpts); +}); diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/src/index.js b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/src/index.js new file mode 100644 index 0000000..d3f5422 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/src/index.js @@ -0,0 +1,9 @@ +import template from "./template.marko"; + +export function handler(req, res) { + if (req.url === "/") { + res.statusCode = 200; + res.setHeader("Content-Type", "text/html; charset=utf-8"); + template.render({}, res); + } +} diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/src/template.marko b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/src/template.marko new file mode 100644 index 0000000..bb153c1 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/src/template.marko @@ -0,0 +1,14 @@ +import { thing } from 'dep'; + + + + + Hello World + + + +

${thing()}

+ + + + diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/test.config.ts b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/test.config.ts new file mode 100644 index 0000000..77ab0a0 --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/test.config.ts @@ -0,0 +1 @@ +export const ssr = true; diff --git a/src/__tests__/fixtures/isomorphic-commonjs-module-exports/vite.config.mts b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/vite.config.mts new file mode 100644 index 0000000..114ba7d --- /dev/null +++ b/src/__tests__/fixtures/isomorphic-commonjs-module-exports/vite.config.mts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; + +export default defineConfig({ + ssr: { + noExternal: ["dep"], + }, +}); diff --git a/src/cjs-to-esm.ts b/src/cjs-to-esm.ts new file mode 100644 index 0000000..df6d491 --- /dev/null +++ b/src/cjs-to-esm.ts @@ -0,0 +1,135 @@ +import { init, parse as parseCommonjs } from "cjs-module-lexer"; +import { init as initEsm, parse as parseEsm } from "es-module-lexer"; +import MagicString from "magic-string"; + +const REQUIRE_RE = /([^.\w$]|^)require\s*\(\s*(['"])(.*?)\2\s*\)/g; +const REQUIRE_TEST_RE = /([^.\w$]|^)require\s*\(\s*['"]/; +const EXPORTS_RE = /\b(module\.exports|exports)\b/; +const CJS_INTEROP_HELPER = `function __cjs_default__(ns) { + var keys = Object.getOwnPropertyNames(ns); + var hasNamed = false; + var hasDefault = false; + for (var i = 0; i < keys.length; i++) { + var k = keys[i]; + if (k === "default") { + hasDefault = true; + } else if (k !== "__esModule" && k !== "module.exports") { + try { if (ns[k] != null) hasNamed = true; } catch(e) {} + } + } + if (hasNamed) return ns; + if (hasDefault) return ns["default"]; + return ns; +}`; + +let initialized = false; + +export async function transformCjsToEsm( + code: string, + _id: string, +): Promise<{ + code: string; + map: ReturnType; +} | null> { + if (!EXPORTS_RE.test(code) && !REQUIRE_TEST_RE.test(code)) { + return null; + } + + if (!initialized) { + await Promise.all([init(), initEsm]); + initialized = true; + } + + const [esImports, esExports] = parseEsm(code); + if (esImports.length || esExports.length) { + return null; + } + + const s = new MagicString(code); + const imports: string[] = []; + const seen = new Map(); + let counter = 0; + let needsHelper = false; + let match: RegExpExecArray | null; + + REQUIRE_RE.lastIndex = 0; + + while ((match = REQUIRE_RE.exec(code))) { + const [fullMatch, prefix, , specifier] = match; + const matchStart = match.index + prefix.length; + const matchEnd = match.index + fullMatch.length; + + let varName = seen.get(specifier); + if (!varName) { + varName = `__cjs_ns_${counter}__`; + seen.set(specifier, varName); + imports.push(`import * as ${varName} from ${JSON.stringify(specifier)};`); + counter++; + } + + needsHelper = true; + s.overwrite(matchStart, matchEnd, `__cjs_default__(${varName})`); + } + + if (needsHelper) { + imports.unshift(CJS_INTEROP_HELPER); + } + + if (imports.length > 0) { + s.prepend(imports.join("\n") + "\n"); + } + + if (EXPORTS_RE.test(code)) { + s.prepend( + `var exports = {};\n` + + `var module = {\n` + + ` get exports() { return exports; },\n` + + ` set exports(value) { exports = value; },\n` + + `};\n`, + ); + + const { exports: cjsExports, reexports } = parseCommonjs(code); + const named = cjsExports.filter( + (e) => e !== "__esModule" && e !== "default", + ); + const isEsModule = cjsExports.includes("__esModule"); + const hasDefault = cjsExports.includes("default"); + + if (named.length > 0) { + const vars = named.map((_name, i) => `__export${i}`); + s.append( + `\nvar ${vars.join(", ")};\n` + + `if (Object.isExtensible(module.exports)) {\n` + + named + .map( + (name, i) => + ` ${vars[i]} = module.exports[${JSON.stringify(name)}];`, + ) + .join("\n") + + `\n}\n`, + ); + s.append( + `export { ${named.map((name, i) => `${vars[i]} as ${JSON.stringify(name)}`).join(", ")} };\n`, + ); + } + + if (isEsModule) { + if (hasDefault || named.length === 0) { + s.append( + `export default (module.exports != null && typeof module.exports === 'object' && 'default' in module.exports ? module.exports.default : module.exports);\n`, + ); + } + } else { + s.append(`export default module.exports;\n`); + } + + for (const reexport of reexports) { + s.append(`export * from ${JSON.stringify(reexport)};\n`); + } + } + + return { + code: s.toString(), + map: s.generateMap({ hires: true }), + }; +} diff --git a/src/index.ts b/src/index.ts index 3acf0ae..b3f939c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,7 @@ import cjsInteropTranslate, { cjsInteropHelpersCode, cjsInteropHelpersId, } from "./cjs-interop-translate"; +import { transformCjsToEsm } from "./cjs-to-esm"; import globImportTransformer from "./glob-import-transform"; import { type DocManifest, @@ -112,11 +113,6 @@ const babelConfig = { const optimizeKnownTemplatesForRoot = new Map(); let registeredTagLib = false; -// This package has a dependency on @parcel/source-map which uses native addons. -// Some environments like Stackblitz don't support loading these. So... load it -// with a dynamic import to avoid everything failing. -let cjsToEsm: typeof import("@chialab/cjs-to-esm").transform | null | undefined; - function noop(): undefined {} export default function markoPlugin(opts: Options = {}): vite.Plugin[] { @@ -809,21 +805,10 @@ export default function markoPlugin(opts: Options = {}): vite.Plugin[] { ext === ".cjs" || (ext === ".js" && isCJSModule(id, rootResolveFile)) ) { - if (cjsToEsm === undefined) { - try { - cjsToEsm = (await import("@chialab/cjs-to-esm")).transform; - } catch (err) { - console.error(err); - cjsToEsm = null; - return null; - } - } - if (cjsToEsm) { - try { - return await cjsToEsm(source); - } catch { - return null; - } + try { + return await transformCjsToEsm(source, id); + } catch { + return null; } } }