rollup packs react components

This time, the main simple implementation is to use rollup to package react components. For components, simply write a pop-up window component. The effect is as follows:

Click to open the pop-up box, click the close button to close the pop-up box

First create a react project, here is still created with mfex-project scaffolding

mfex-project create react-demo

Then write the dialog component

code show as below:

components/dialog/index.tsx

import './index.scss';
import closeIcon from '@/assets/close-black.png'
interface IProps {
    show: boolean;
    title?: string;
    handleCloseAction: () => void
}
function Dialog(props: IProps) {
    const handleClose = () => {
        props. handleCloseAction()
    }
    return (
        props.show? <div className='dialog'>
            <div className='dialog-content'>
                <img src={closeIcon} alt="" className='dialog-content-close' onClick={handleClose}/>
                <h1 className='dialog-content-title'>{props.title}</h1>
            </div>
        </div> : <></>
    )
}
export default Dialog;

components/dialog/index.scss

.dialog{
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    background: rgba(0,0,0,.6);
    z-index: 990;
     &-content{
        width: 500px;
        height: 300px;
        background: #fff;
        border-radius: 25px;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%,-50%);
         &-close{
            width: 30px;
            height: 30px;
            position: absolute;
            right: 20px;
            top: 20px;
            
        }
         &-title{
            margin-top: 20px;
            text-align: center;
        }
    }
}

Introduce and use components:

import './index.scss';
import Dialog from '@/components/dialog'
import { useState } from 'react'
function Index() {
    const [dialogShow, setDialogShow] = useState<boolean>(false)
    const handleCloseAction = () => {
        setDialogShow(false)
    }
    return (
        <>
            <div className='index'></div>
            <div className='w-100px h-100px bg-blue-300' onClick={()=>setDialogShow(true)}>Open dialog</div>
            <Dialog show={dialogShow} title='rollup' handleCloseAction={handleCloseAction}/>
        </>
    )
}
export default Index;

Next, wrap the component with rollup

1. Create a folder, name it react-dialog, and initialize the project

npm init -y

2. Install rollup

npm i rollup -D

3. Install the plug-in

  • @rollup/plugin-node-resolve: Help rollup recognize external modules

  • @rollup/plugin-babel: ES6 to ES5

  • @rollup/plugin-commonjs: convert commonjs module to es module

  • @rollup/plugin-terser: code minification

  • rollup-plugin-img: processing images

  • rollup-plugin-postcss: process css

  • @rollup/plugin-json: handle json

  • @rollup/plugin-typescript: handles typescript

  • rollup-plugin-dts: package ts declaration file, d.ts

npm i @rollup/plugin-node-resolve

@rollup/plugin-babel

@rollup/plugin-commonjs

@rollup/plugin-terser

rollup-plugin-img

rollup-plugin-postcss

@rollup/plugin-json

@rollup/plugin-typescript

rollup-plugin-dts -D

4. Install the packages corresponding to css and babel

npm i autoprefixer core-js @babel/core @babel/plugin-transform-runtime @babel/preset-env -D

Create a new .babelrc in the root directory, the content is as follows

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false, // Do not convert ES6 module files to use tree shaking, sideEffects, etc.
        "useBuiltIns": "entry", // all shims not supported by the browserslist environment are imported
        // https://babeljs.io/docs/en/babel-preset-env#usebuiltins
        // https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md
        "corejs": {
          "version": 3, // use core-js@3
          "proposals": true
        }
      }
    ]
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
        {
          "corejs": false // Solve the repeated introduction of helper functions
        }
    ]
  ],
  "ignore": [
    "node_modules/**"
  ]
}

Browserslist needs to be specified to determine the target environment where our program runs, to avoid browser environments that are not considered compatible with the program

Add in package.json:

"browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]

5. Since typescript is used, install typescript and initialize tsconfig.json

npm i typescript -D

npx tsc --init

The content of tsconfig.json is as follows:

{
  "compilerOptions": {
    "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
    "jsx": "react-jsx", /* Specify what JSX code is generated. */
    /* Modules */
    "module": "ESNext", /* Specify what module code is generated. */
    // "rootDir": "./", /* Specify the root folder within your source files. */
    "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
    // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
    /* Emit */
    "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
    // "declarationMap": true, /* Create sourcemaps for d.ts files. */
    "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
    "sourceMap": true, /* Create source map files for emitted JavaScript files. */
    // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
    // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
    "outDir": "dist", /* Specify an output folder for all emitted files. */
    "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
    "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
    // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
    "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
    /* Type Checking */
    "strict": true, /* Enable all strict type-checking options. */
    "skipLibCheck": true, /* Skip type checking all .d.ts files. */
  }
}

6. Next, copy the react component into the project

7. Since the file with the png suffix is used, the file type must be defined, otherwise ts will report an error

Xinjiang index.d.ts in the root directory

declare module '*.png'

8. Modify package.json

 "main": "dist/cjs/index.js",
  "module": "dist/esm/index.js",
  "type": "module",
  "types": "dist/index.d.ts",
  "files": [
    "dist",
    "package.json"
  ],
  "scripts": {
    "build": "rimraf dist & amp; & amp; rollup -c"
  },

9. Write rollup.config.js

import resolve from '@rollup/plugin-node-resolve';
import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import terser from '@rollup/plugin-terser';
import image from 'rollup-plugin-img';
import postcss from 'rollup-plugin-postcss'
import json from '@rollup/plugin-json';
import typescript from '@rollup/plugin-typescript';
import dts from "rollup-plugin-dts";
import autoprefixer from 'autoprefixer'
import path from 'path'
// convert require to module
import { createRequire } from 'module';
const require = createRequire(import.meta.url);

const pkg = require(path. resolve(`package.json`))
export default[
    {
        input: './src/index.tsx',
        output:[
            {
                file:pkg.main,
                format: "cjs",
                sourcemap: true,
                name: "react-dialog-lib"
            },
            {
                file:pkg.module,
                format: "es",
                sourcemap: true,
            }
        ],
        plugins:[
            resolve(),
            typescript(),
            terser(),
            babel({
                exclude: "**/node_modules/**",
                runtimeHelpers: true,
            }),
            commonjs(),
            postcss({
                plugins:[autoprefixer()]
            }),
            json(),
            image({
               
               
                limit: 8192, // default 8192(8k)
                exclude: 'node_modules/**'
              })
        ]
    },
    {
        input: "dist/esm/index.d.ts",
        output:[
            {
                file: "dist/index.d.ts",
                format: "es"
            }
        ],
        external: [/\.scss$/],
        plugins:[
            dts()
        ]
    }
]

10. Run the packaging command, which can be published to npm later, here is just for demonstration

npm run build

Successfully packaged

11. Use in previous projects

import package

npm i

Then

normal display

Problems encountered:

  • When writing a package project, the editor will not recognize the react syntax

    React’ refers to a UMD global, but the current file is a module. Consider adding an import instead add “jsx”: “react-jsx” to tsconfig.json,

  • Cannot find module ‘react/jsx-runtime’ or its corresponding type declarations. JSX element implicitly has type ‘any’ because no interface ‘JSX.IntrinsicElements’ exists. Need to install @types/react

    npm i @types/react -D