The cause of

  • Some time ago, the company was doing the extraction of public components and planned to create a public component library. The original idea was to directly introduce encapsulated public components into the project and then use them. Later, it was found that direct reference would report errors, which roughly meant that direct introduction could not be recognizedjsxGrammar and things like that.
  • Then refer to each ready-made class libraryantd,elementUISuch UI library practices are packaged and generated for other projects to introduce usees,lib,umdSuch as format.
  • The decision was made to introduce the same packaging mechanism to automatically generate code formats used in different environments

To solve the process

Research which packaging plan to usewebpackorrollup

Webpack

  • WebpackCreated by Tobias Koppers in 2012 to solve a problem that tools at the time couldn’t handle: building complex single-page applications (spAs)
  • The code segment:WebpackDivide your app into manageable chunks that can be loaded on demand when users use your app. This means faster interaction for your users
  • Static resource import: Images, CSS and other static resources can be directly imported into your app, just like other modules, nodes can be dependency management. As a result, we no longer have to carefully place each static file in a specific folder and then use a script to hash the file URL. Webpack has done all this for you.

rollup

  • Tree Shaking: this isrollupProposed a feature that utilizeses6The static characteristics of modules analyze imported modules and extract only the methods used to reduce the packaging volume.
  • The configuration is simple to use and generates code relative toWebpackMore concise.
  • You can specify a variety of different modules to be used in production (amd.commonjs.es.umd).

Similarities and differences between

  • WebpackMore suitable for our actual business project packaging, the code and static resources for packaging, segmentation, dynamic introduction without our manual processing.
  • rollupCompact and easy to use configurationlibClass libraries are packaged, and code runs more efficiently fromvue.reactAnd other popular frame hugsrollupYou can see the signs.
  • WebpackPackaging configuration is relatively cumbersome, the volume of packaged code is relatively large, and there will be dependency search between different dependencies, which is less efficientrollup
  • A rude conclusion: there is code and all kinds of static resources for everyday single-page applicationsWebpackMore suitable for some pure JS/TS library projectsrollupMore suitable for,rollupPackaged input can be specified in different formats (amd.commonjs.es.umd) should be introduced into various scenarios.

Packaging implementation

  • In summary, this package is a UI library used in other projects. Although static resources such as style files and image files exist in this project, they are used in rollup@rollup/plugin-imageandrollup-plugin-postcssTwo plug-ins to handlecss/lessandimgProcess.
  • The configuration procedure is as follows (a comment is made to explain the functions of each configuration and dependency based on the actual configuration) :
    • The installationrollupAnd rely on
    yarn add -D rollup rollup-plugin-babel rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-replace  @rollup/plugin-image rollup-plugin-terser rollup-plugin-uglify rollup-plugin-postcss cssnano postcss-cssnext postcss-nested postcss-simple-vars
    Copy the code
    • installedrollupYou need to configure it laterbabel, also need to installbabelConfigure the relevant plug-in dependencies required
    yarn add -D @babel/cli @babel/core @babel/plugin-external-helpers @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-proposal-object-rest-spread @babel/plugin-transform-react-display-name @babel/plugin-transform-react-jsx @babel/plugin-transform-runtime @babel/preset-env
    Copy the code
    • After the above development dependencies are installedrollupandbabelIn the root directory of the projectrollup.config.jsand.babelrc.jsTwo profiles are used forrollupandbabelRead at run time.
    • rollup.config.jsThe configuration is as follows:
      // Rollup plugins
      // The Babel plug-in handles the conversion of ES6 code so that it can be used in environments that do not support ES6
      import babel from 'rollup-plugin-babel';
      // Resolve merges the source code we wrote with dependent third-party libraries
      import resolve from 'rollup-plugin-node-resolve';
      Rollup.js does not recognize CommonJS modules
      import commonjs from 'rollup-plugin-commonjs';
      // Global substitution variables such as process.env
      import replace from 'rollup-plugin-replace';
      // Enable rollup to use postCss to process style files less, CSS, etc
      import postcss from 'rollup-plugin-postcss';
      // Can handle the way in which images are imported from components, converting them to Base64 format, but with increased packaging volume, suitable for small ICONS
      import image from '@rollup/plugin-image';
      // Compress the package code (deprecated here because the plugin does not recognize es syntax, so terser is used instead)
      // import { uglify } from 'rollup-plugin-uglify';
      // Compress the packaging code
      import { terser } from 'rollup-plugin-terser';
      // import less from 'rollup-plugin-less';
      // PostCSS plugins
      // Handle CSS defined variables
      import simplevars from 'postcss-simple-vars';
      // Handle less nested style writing
      import nested from 'postcss-nested';
      // The latest CSS features can be preset (deprecated by postCSs-preset -env, but used)
      // import cssnext from 'postcss-cssnext';
      / / replace cssnext
      import postcssPresetEnv from 'postcss-preset-env';
      // CSS code compression
      import cssnano from 'cssnano';
      
      const env = process.env.NODE_ENV;
      
      export default {
        I export all custom components under components
        input: 'src/components/index.js'.// Output folder, can be an array output in different formats (umd, CJS,es...) Env is a production environment package to determine whether the file is named.min
        output: [{
          file: `dist/dna-ui-react-umd${env === 'production' ? '.min' : ' '}.js`.format: 'umd'.name: 'geneUI'}, {file: `dist/dna-ui-react-es${env === 'production' ? '.min' : ' '}.js`.format: 'es'}].// Inject global variables such as $in jQuery
        // globals: {
        // react: 'react ', // global.react is an external dependency on react
        // antd: 'antd'
        // },
        THIS_IS_UNDEFINED warning will be reported, which will be filtered manually
        onwarn: function (warning) {
          if (warning.code === 'THIS_IS_UNDEFINED') {
            return; }},// Treat modules as external modules and not packaged in libraries
        external: ['antd'.'@ant-design/icons'.'react'.'prop-types'.'gojs']./ / the plugin
        plugins: [
          image(),
          postcss({
            plugins: [
              simplevars(),
              nested(),
              // cssnext({ warnForDuplicates: false, }),
              postcssPresetEnv(),
              cssnano(),
            ],
            // Process.css and.less files
            extensions: [ '.css'.'less' ],
          }),
          resolve(),
          // Babel processes all js that do not contain node_modules files
          babel({
            exclude: '**/node_modules/**'.runtimeHelpers: true.plugins: [
              "@babel/plugin-external-helpers"]}),// There are apis that are imported to use a library but are not exported manually via namedExports
          commonjs({
            'namedExports': {
              'node_modules/react-is/index.js': ['isFragment'].'node_modules/react/index.js': ['Fragment'.'cloneElement'.'isValidElement'.'Children'.'createContext'.'Component'.'useRef'.'useImperativeHandle'.'forwardRef'.'useState'.'useEffect'.'useMemo'].'node_modules/react-dom/index.js': ['render'.'unmountComponentAtNode'.'findDOMNode'].'node_modules/gojs/release/go.js': ['Diagram'.'GraphLinksModel'.'Overview'.'Spot']}}),// Replace NODE_ENV globally. Exclude excludes files in certain folders
          replace({
            // exclude: 'node_modules/**',
            'process.env.NODE_ENV':  JSON.stringify(env || 'development'),}),// Production environment executes terser compression code
          (env === 'production' && terser()),
        ],
      }
    Copy the code
    • .babelrc.jsThe configuration is as follows:
      // Use cross-env to inject different execution variables to make sure Babel transcodes into different formats es and commonJS
      const { NODE_ENV, BABEL_ENV } = process.env
      const cjs = NODE_ENV === 'test' || BABEL_ENV === 'commonjs'
      const loose = true
      
      module.exports = {
        // Set modules:false to avoid rollup errors after Babel is converted to CommonJS
        presets: [['@babel/env', { loose, modules: false }]],
        plugins: [['@babel/proposal-decorators', { legacy: true }],
          ['@babel/proposal-object-rest-spread', { loose }],
          // Convert JSX syntax
          '@babel/transform-react-jsx',
          cjs && ['@babel/transform-modules-commonjs', { loose }],
          [
            '@babel/transform-runtime',
            {
              useESModules: !cjs,
              version: require('./package.json').dependencies[
                '@babel/runtime'
              ].replace(* / / ^ ^ 0-9].' ')}], ["@babel/plugin-proposal-class-properties"]
        ].filter(Boolean)}Copy the code
    • The above is installedrollupandbabelDependency, after configuring the corresponding configuration can be configured to execute commands inpackage.jsonIn:
     "rollup-build": "cross-env BABEL_ENV=rollup rollup -c"."rollup-production-build": "cross-env NODE_ENV=production rollup -c".Copy the code

    Rollup -c refers to the default execution of rollup.config.js in the root directory

    • Execute the above commandyarn rollup-buildandyarn rollup-production-buildAfter therollup.config.jstheoutputThe configuration indistDirectory to generate the corresponding package file. The generated files can be imported directly using the component library for the corresponding environment.

One day

  1. The above configuration can package the code into a JS file for import and use, while careful students should be able to find some class libraries havelib.esFolders are used to representcommonjsWriting andes6The way we write it, we can usebabelDirect transcoding generation.
  • We have one in the root directory.babelrc.jsIs configured for executionbabelThe configuration.
  • All we have to do ispackage.jsonthescriptsAdd the following command:
  "build:commonjs": "rimraf lib && cross-env BABEL_ENV=commonjs babel src --out-dir lib"."build:es": "rimraf es && cross-env BABEL_ENV=es babel src --out-dir es".Copy the code
  • Execute the above command to generate the corresponding module code.
  1. seeantdandelementUIUI library, such as the document station combined with the source found that the document station is written by Markdown document, and then through the corresponding conversion tool into a static document station. Two static site generators that collect documents are recommended:
  • doczIs aimed atreact, where developers can introduce their own components into the correspondingmarkdownthe.mdxFile, the bottom layer is usedgatsbyStatic site builder, but usedoczthereactScaffolding pit, need to be prepared.
  • storybookIs a more powerful document generator that can supportjsx..vueVarious components are also supported.mdxDocument writing.

To move the brick

  • rollup
  • 10 minutes for quick advancement rollup.js
  • All that rollup stuff