背景:项目中要求将一个模块的应用打成组件,上传到公司私服供其他项目组使用,你没有听错是打整个模块的应用,并不是一个单纯的react组件,它里面包含了特别多的内容,一言难尽,抱着从来没打过组件包的我,充满好奇的接下了这个担子,开始学习。
在网上一通查找,最终确定了一个各方面都比较好的打包工具,rollup为什么选择它,因为antd也是它打出来的哦,所以它应该也不会差。
第一步,根据官方文档,以及网上的各位大佬,东拼西凑,打出了一个基本的button组件。放到npm可下载,方案基本确定可行性后,开始对项目进行打包部署,因为代码比较多,所以我直接copy整个模块的代码,单独维护其store以及全局方法等等。
先给看一下我本地的配置所需要的包,后面会贴上全部配置
万事俱备开始打包
噩梦开始了 yarn build 一堆错误图片资源未打包成base64,同一个资源文件,公共资源文件只需要在顶层引入,如果在内部样式文件引入,rollup不会再次对相同资源进行编译打包,我下面的配置基本上能解决98%的问题,大家对相关的包如果不清楚,可以去rollup官方去了解
打包入口文件配置
必须以这种格式进行导出
对自己的组件可单独写一个ts文件进行组件以及类型声明,然后引入到上面定义的入口文件
打包后的输出
打包后会生产es模块,这个模块就是最终要发布的模块
pagejson配置
每次发布的版本号必须不一样,不然会发布失败 发布命令npm publish 不要使用yarn publish 会存在一定的问题
下面是全部配置
import alias from '@rollup/plugin-alias';
import commonjs from "@rollup/plugin-commonjs";
import resolve from '@rollup/plugin-node-resolve'
import strip from "@rollup/plugin-strip";
import typescript from "@rollup/plugin-typescript";
import autoprefixer from 'autoprefixer';
import path from 'path';
import externals from 'rollup-plugin-node-externals';
import postcss from 'rollup-plugin-postcss';
import replace from 'rollup-plugin-replace';// 替换待打包文件里的一些变量,如 process在浏览器端是不存在的,需要被替换
import serve from 'rollup-plugin-serve';
import pkg from "./package.json";
import json from 'rollup-plugin-json';
import { config } from 'dotenv';
import babel from 'rollup-plugin-babel';
import postUrl from 'postcss-url';
//打包import引入的资源图片地址
import image from "@rollup/plugin-image";
//对包进行压缩
import { terser } from 'rollup-plugin-terser';
//每次打包清除指定目录
import del from 'rollup-plugin-delete'
import globals from 'rollup-plugin-node-globals';
import nodePolyfills from 'rollup-plugin-node-polyfills';
import postImport from 'postcss-import';
const NODE_ENV = process.env.NODE_ENV
const resolveDir = dir => path.join(__dirname,dir)
// 获取文件里面的内容
let envConfig = config({ path: "./.env."+ NODE_ENV }).parsed;
console.log('envConfig_____________',envConfig)
const extensions = [".js", ".jsx",".ts",".tsx",".json"];
// amd – 异步模块定义,用于像RequireJS这样的模块加载器
// cjs – CommonJS,适用于 Node 和 Browserify/Webpack
// es – 将软件包保存为ES模块文件
// iife – 一个自动执行的功能,适合作为<script>标签。(如果要为应用程序创建一个捆绑包,您可能想要使用它,因为它会使文件大小变小。)
// umd – 通用模块定义,以amd,cjs 和 iife 为一体
const Global = `var process = {
env: {
NODE_ENV: 'production'
}
}`
export default [
{
input: './src/index.ts',//如果是本地开发则使用index.tsx
external: [
'antd',
'react',
'redux',
'react-dom',
'react-redux',
'lodash',
'axios',
],// 告诉rollup,不打包这些模块;将其视为外部依赖
// /*
// 打包配置
output: [{
dir: path.dirname(pkg.module),
format: "es",
name: pkg.name,
exports: 'named', // 指定导出模式(自动、默认、命名、无)
preserveModules: true, // 保留模块结构
preserveModulesRoot: 'src', // 将保留的模块放在根级别的此路径下
// 添加globals
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'axios': 'axios',
jQuery: "jquery",
$: "jquery",
},
banner:Global,
}],
mode: 'production',//自动开启代码压缩、Tree Shaking、Scope Hoisting等优化功能,以减小生成的代码体积和提高执行效率
plugins: [
resolve({
extensions,
}),
commonjs({
extensions,
}),
// 使用别名 感觉这个配置没有鸟用...
alias({
entries: [{ find: '@', replacement: resolveDir('src') }],
}),
typescript({
"outDir": "es",
"declaration": true,
"declarationDir": "es"
}),
postcss({
to: './src/assets',
extensions: [".less",".scss", ".css"],
use: [[
"less", {
javascriptEnabled: true,
includePaths:'src'
},
]],
inject:true,
plugins: [
postUrl({// 支持css引入静态资源
url: "inline", // 转成base64
maxSize: 900000000, // 转base64的文件大小界限
fallback: "copy", // 转不了base64时的操作
}),
autoprefixer(),
postImport(),
],
extract:'css/index.css',
minimize: true,//压缩css
sourceMap: true,
}),
image({
include: ['**/*.png', '**/*.jpg', '**/*.svg']
}),
strip(),
del({targets: ['es/*']}),
externals({
devDeps: false,
}),
json(),//解析json文件
globals(),
nodePolyfills(),
replace({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.proxy': JSON.stringify(envConfig.proxy),
'process.env.API_FILE_HOST': JSON.stringify(envConfig.API_FILE_HOST),
'process.env.API_PROTOCOL': JSON.stringify(envConfig.API_PROTOCOL),
'process.env.KC_SERVICE_IP': JSON.stringify(envConfig.KC_SERVICE_IP),
'process.env.NODE_DEBUG': JSON.stringify(envConfig.NODE_DEBUG),
'process.env.BASE_URL': JSON.stringify(envConfig.BASE_URL),
}),
babel({// 转义 ES6/7 代码为 ES5
babelrc: false,
exclude: "node_modules/**", // 排除node_modules 下的文件
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: [
[
"import",
{
libraryName: "antd",
libraryDirectory: "es",
style: true
},
"antd",
],
],
}),
terser(),
NODE_ENV === 'development'? serve({
open:true,
openPage:'/public/index.html', // 默认打开html的路径
port:3000,
contentBase:["dist"]
}):null
],
},
];
感谢观看 希望多多交流