这次主要简单实现用rollup打包react组件,组件的话简单写了一个弹窗组件,效果如下:
点击打开弹框,点击关闭按钮关闭弹框
首先创建react项目,这边还是用mfex-project脚手架创建
mfex-project create react-demo
然后编写dialog组件
代码如下:
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;}}
}
引入使用组件:
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)}>打开dialog</div><Dialog show={dialogShow} title='rollup' handleCloseAction={handleCloseAction}/></>)
}
export default Index;
接下来用rollup把组件封装
1、创建文件夹,命名为react-dialog,初始化项目
npm init -y
2、安装rollup
npm i rollup -D
3、安装插件
-
@rollup/plugin-node-resolve:帮助 rollup 识别外部模块
-
@rollup/plugin-babel:ES6转ES5
-
@rollup/plugin-commonjs:将commonjs模块转为es模块
-
@rollup/plugin-terser:代码压缩
-
rollup-plugin-img:处理图片
-
rollup-plugin-postcss:处理css
-
@rollup/plugin-json:处理json
-
@rollup/plugin-typescript:处理typescript
-
rollup-plugin-dts:打包ts声明文件,d.ts
npm i @rollup/plugin-node-resolve@rollup/plugin-babel@rollup/plugin-commonjs@rollup/plugin-terserrollup-plugin-imgrollup-plugin-postcss@rollup/plugin-json@rollup/plugin-typescriptrollup-plugin-dts -D
4、安装css和babel对应的包
npm i autoprefixer core-js @babel/core @babel/plugin-transform-runtime @babel/preset-env -D
根目录下新建.babelrc,内容如下
{"presets": [["@babel/preset-env",{"modules": false, // 对ES6的模块文件不做转化,以便使用tree shaking、sideEffects等"useBuiltIns": "entry", // browserslist环境不支持的所有垫片都导入// 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, // 使用core-js@3"proposals": true}}]],"plugins": [["@babel/plugin-transform-runtime",{"corejs": false // 解决 helper 函数重复引入}]],"ignore": ["node_modules/**"]
}
需要指定 browserslist 来确定我们程序运行的目标环境,避免去兼容程序不考虑的浏览器环境
在package.json添加:
"browserslist": ["> 1%", "last 2 versions","not ie <= 8"]
5、由于是使用typescript,所以安装typescript,并初始化tsconfig.json
npm i typescript -Dnpx tsc --init
tsconfig.json内容如下:
{"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、接下来把react组件copy到项目中
7、由于使用了png后缀的文件,所以要定义文件类型, 不然ts会报错
在根目录下新疆index.d.ts
declare module '*.png'
8、修改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 && rollup -c"},
9、编写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'
// 讲require转换为模块
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、运行打包命令,后续可以发布到npm上,这里只是作为演示
npm run build
打包成功
11、在之前的项目的使用
引入包
npm i
然后
正常显示
遇到的问题:
- 在编写包项目时,编辑器会无法识别react的语法
React' refers to a UMD global, but the current file is a module. Consider adding an import instead 在tsconfig.json中加上 "jsx": "react-jsx",
-
Cannot find module 'react/jsx-runtime' or its corresponding type declarations. JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists. 需要安装@types/react
npm i @types/react -D