react-imported-component
react-imported-component copied to clipboard
react importeted components and esbuild-loader or swc-loader
Hi, Is there a possibility to use this library with other bundlers or other loaders to speed up the process of building and rebuilding applications?
In my understanding, this library is dependent on babel because we need babel plugins to get it to work, right?
Correct. It can "work" with esbuild/swc by calling babel only for the files with dynamic imports, which is just a few files among others, maintaining build speed and not losing functionality.
The corresponding plugin can be done in the form of webpack or rollup(vite) loader - checking for a keywords/import and running targeted babel transform if needed.
@theKashey in our architecture we have about 250 (sic!) lazy loaded components. We put all lazy imports in to few files. Lets say commonLazyImports
and themedLazyImports
(we have support for few themes in our app).
Do we have to transfer only files with usage of lazy import, or also in the places where we use lazy components?
Ex structure
commonLazyImport.tsx
const component = lazy(() => import('./component.tsx')
OtherComponent.tsx
import Component from `./commonLazyImport.tsx`
export const OtherComponent = () => <Component />
So do we have to transform both commonLazyImport.tsx
and OtherComponents.tsx
?
Only files with dynamic imports need the babel pass, that is commonLazyImport
and index file (the one generated by imported-components
command)
Also - babel is required only for SSR, for clientside-only activities it is not required at all.
Ok, finally we did, however right after we realized that our build time does not have problems with ts(x) files :)
However, I will leave it for someone who also decides to use react-imported-components
with esbuild-loader
or swc-loader
About app
~250k line of code Our application has a theming mechanism. It's not only about CSS, but also about HTML structure and logic. So we decided to load tsx files related to other themes by lazy loading from this library.
File structure
So in our architecture, we have a couple of files related to react-imported-component
library.
- lazyImports.tsx <- We have here all lazy imports common for the whole app
- firstThemeLazyImports.tsx <- We have here all lazy imports for the first theme
- secondThemeLazyImports <- We have second theme lazy imports
Also, we are generating by imported-components
command extra files:
- common-chunks.ts <- for common lazy imports
- firstTheme-chunks.ts <- for first theme lazy imports
- secondTheme-chunks.ts <- for second theme imports
Example webpack loaders config client
Example webpack loaders config server
On the server we use the extra plugin for babel dynamic-import-node
, not sure if required, for other setups
Final results
Unfortunately, it didn't give as spectacular results. The problem with esbuild-loader and swc-loader (both work with same speed with no problems at all) is that they don't have built caching mechanism and babel-loader does ;) We could use webpack cache system but it does not work in our code base (large ecommerce app). Also, we tried cache-loader and thread-loader, but both didn't give us any benefits. (We kept thread-loader)
In general with cached babel, build takes 22s to transpile tsx, esbuild and swc about 16s.
Development build with cached babel takes 40s, with esbuild and swc 38s :) However, babel without cache takes 60s. So at least esbuild and swc do not require any cache to have
Reason
The reason is our SCSS build system. Even if tsx files are transpired in less than 20s. We have so many scss files that takes about 40s to transpile :) So even if we speed up the process of transpiring typescript, we are still blocked by SCSS :)
Problem with babel can be resolved via customer loader like
// chatGpt generated
const babelLoader = require('babel-loader');
module.exports = function(source, sourceMap) {
// Check if the source code contains the magic string
const hasMagicString = source.includes('react-imported-component'); // ⬅️⬅️
if (hasMagicString) {
// pass down to babel
return babelLoader.call(this, source, sourceMap);
}
// If the magic string is not present, return the original source code
return [source, inputSourceMap]
};
In webpack config you can apply this loader to all js/ts files passing babel configuration into options and it will execute babel transform only for the files that needed it.
The only "cost" you have to pay - source.includes - which is "nothing"