react-imported-component icon indicating copy to clipboard operation
react-imported-component copied to clipboard

react importeted components and esbuild-loader or swc-loader

Open KoderFPV opened this issue 1 year ago • 5 comments

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?

KoderFPV avatar Feb 05 '24 16:02 KoderFPV

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 avatar Feb 06 '24 07:02 theKashey

@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?

KoderFPV avatar Feb 06 '24 10:02 KoderFPV

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.

theKashey avatar Feb 07 '24 09:02 theKashey

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

image

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

image

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 :)

KoderFPV avatar Feb 08 '24 13:02 KoderFPV

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"

theKashey avatar Feb 09 '24 23:02 theKashey