web-infra-dev / rsbuild

The Rspack-based build tool. It's fast, out-of-the-box and extensible.
https://rsbuild.dev/
MIT License
1.02k stars 77 forks source link

[Feature]: insert library urls into html when externals are setup #1042

Closed xc2 closed 5 months ago

xc2 commented 6 months ago

What problem does this feature solve?

when one is setup a web app build with externals in it, 90% of those will typically also inject <script> or <link> of these external libraries into html - sometimes a set of unpkg urls, sometimes the file urls inside the public directory.

in some setup, the developer would config externals only for production mode.

The most common thing is: when bump up a dependency of this web app, most of developers bump only the dependency entity in package.json and forget the link in html.

I previously use my own version of html-webpack-deploy-plugin to achieve it. I think rsbuild could support this feature.

pros of html-webpack-deploy-plugin:

cons:

What does the proposed API look like?

An example option:

It looks very like html-webpack-deploy-plugin.

{
  // 4.3 should use cdn url. field scope: resources | global. 
  useCdn: false,
  // 4.4 function to generate cdn url. field scope: resources | global.
  getCdnUrl: undefined,
  resources: [
      {
        // 1. package name
        package: 'react',
        // 2. copy files with glob `umd/*.js` to somewhere like `{bundler dist}/libraries/[package]@[version]/[name].[ext]`
        copy: [{ from: 'umd/*.js', to: '[name].[ext]' }],
        // 4. config for js(scripts) or css(links). T[] or T.
        scripts: {
          // 3. variable name exported from umd file, generally for `webpack.externals`
          variableName: 'React',
          // 4.1 path for production build
          path: 'react.production.min.js',
          // 4.2 alternative path for development build. notice that react's dev build is mandatory for react hmr in some case.
          devPath: 'react.development.js',
          // 4.3 should use cdn url. field scope: resources | global. 
          useCdn: false,
          // 4.4 function to generate cdn url. field scope: resources | global.
          getCdnUrl: undefined,
          // 4.5 <script> attributes
          attributes: scriptAttrs,
        },
      },
      {
        package: 'react-dom',
        copy: [{ from: 'umd/*.js', to: '[name].[ext]' }],
        scripts: {
          variableName: 'ReactDOM',
          path: 'react-dom.production.min.js',
          devPath: 'react-dom.development.js',
          attributes: scriptAttrs,
        },
      },
      {
        package: 'react-router-dom',
        copy: [{ from: 'umd/*.js', to: '[name].[ext]' }],
        scripts: [
          {
            variableName: 'ReactRouterDOM',
            path: 'react-router-dom.min.js',
            devPath: 'react-router-dom.js',
            attributes: scriptAttrs,
            // 4.6 add this script into html only when react-router-dom is used by chunks.
            onlyUsed: true
          },
        ],
        // 5. extra `webpack.externals` provided by this package. ( react-router-dom's umd file provides `react-router` too)
        extraExternals: { 'react-router': 'ReactRouterDOM' },
      },
      {
        package: '@douyinfe/semi-ui',
        copy: [{ from: 'dist/{umd,css}/*.{js,css}', to: '[name].[ext]' }],
        // 4. links
        links: { path: 'semi.min.css', devPath: 'semi.css' },
        scripts: {
          variableName: 'SemiUI',
          path: 'semi-ui-react.min.js',
          devPath: 'semi-ui-react.js',
          attributes: scriptAttrs,
        },
      },
      {
        package: '@douyinfe/semi-theme-nerv',
        copy: [{ from: '*.css', to: '[name].[ext]' }],
        links: { path: 'semi.min.css', devPath: 'semi.css' },
        // 6. this config contains css only
      },
    ]
  }
}
chenjiahan commented 6 months ago

This could be a useful feature, we can provide an Rsbuild plugin to implement it.

Can you share the detailed plugin API design? ❤️

xc2 commented 6 months ago

This could be a useful feature, we can provide an Rsbuild plugin to implement it.

Can you share the detailed plugin API design? ❤️

I've just added an option example.

chenjiahan commented 6 months ago

Look good to me 👍

How about maintain this plugin in a separate repo? Maybe create a new repo in https://github.com/rspack-contrib.

I hope to reduce the complexity of the Rsbuild repo and hand over more non-core plugins over to the community for maintenance.

xc2 commented 6 months ago

Look good to me 👍

How about maintain this plugin in a separate repo? Maybe create a new repo in https://github.com/rspack-contrib.

I hope to reduce the complexity of the Rsbuild repo and hand over more non-core plugins over to the community for maintenance.

absolutely

chenjiahan commented 6 months ago

You can give me a repo name when you are going to start the work, I will create the repo and add admin role for you. 😄

chenjiahan commented 5 months ago

I will move this issue to discussion, as this feature will be supported by a separate Rsbuild plugin.