Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(build): address issue with dynamic import and vite (#5399)
When we added a script for building the modules in `internal/` with Esbuild in #5276 we needed to make a change to the function that Stencil uses at runtime to lazy-load components (in `src/client/client-load-module.ts`). Prior to #5276 we had a dynamic import statement which looked like so: ```ts import( `./${bundleId}.entry.js${BUILD.hotModuleReplacement && hmrVersionId ? '?s-hmr=' + hmrVersionId : ''}` ) ``` This constructs a filepath to the module for a given Stencil component, accounting for HMR versioning, and then imports the module. All well and good, but unfortunately this dynamic import does not play well with Esbuild. As described [here](https://esbuild.github.io/api/#non-analyzable-imports) when Esbuild is in 'bundle' mode and it encounters an `import()` _and_ the imported path or identifier looks "analyzable" it will attempt to resolve the corresponding file and incorporate it into the bundle. This is not always what you want! In particular, in our situation the leading `"./"` in the template literal we had in `client-load-module.ts` caused Esbuild to consider the `import()` an "analyzable" import and it then tried to resolve and bundle the import instead of just leaving the dynamic import in the code (as Rollup does in this case). This created an issue because at _compile time_ (i.e. when Stencil itself is built) this import does not resolve to anything, so Esbuild would essentially transform that line into an empty import. This caused runtime issues because the side-effect of the dynamic import was no longer happening, so the modules containing Stencil component classes and so on were not longer being loaded in. To get this working for #5276 we pulled out the `"./"` string as a separate variable, changing the template literal so it looks something like this: ```ts const MODULE_IMPORT_PREFIX = './'; import( `${MODULE_IMPORT_PREFIX}${bundleId}.entry.js${BUILD.hotModuleReplacement && hmrVersionId ? '?s-hmr=' + hmrVersionId : ''}` ) ``` This causes Esbuild to conclude that the import is "non-analyzable", which addresses the issue and causes both Rollup and Esbuild to emit equivalent code for this snippet, where both retain the dynamic import, allowing for the runtime module resolution that we want here. _However_, this broke the ability to use Stencil with Vite, which will complain about non-analyzable imports if it sees a dynamic import which does _not_ begin with `"./"`. See #5389 for details. So essentially we have a situation where the behavior of Rollup, Esbuild, and Vite is incompatible. The solution is to figure out a way for both the Esbuild and Rollup builds to emit code in this case which retains the dynamic import _and_ retains the leading `"./"` in the template literal. This is accomplished by retaining the `${MODULE_IMPORT_PREFIX}` in the template literal, so that Esbuild does not attempt to analyze and bundle the import, and adding plugins to both the Rollup and Esbuild bundles to transform the emitted code before it is written to disk. fixes #5389 STENCIL-1181
- Loading branch information