const path = require('path'); const merge = require('webpack-merge'); const baseConfig = require('./webpack.base.js'); // 引用公共的配置 const devConfig = { entry: './demo/demo.js', // 入口文件 mode: 'development', // 打包为开发模式 output: { filename: 'https://www.jb51.net/demo.bundle.js', // 输出的文件名称 path: path.resolve(__dirname, '../demo') // 输出的文件目录 }, devServer: { // 该字段用于配置webpack-dev-server contentBase: path.join(__dirname, '../demo'), compress: true, port: 9000, // 端口9000 open: true // 自动打开浏览器 }, module: { rules: [ { // 编译less test: /\.less$/, exclude: '/node_modules/', use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'less-loader' }] }, ] }, } module.exports = merge(devConfig, baseConfig); // 将baseConfig和devConfig合并为一个配置
需要注意的是,等会使用webpack-dev-sevrer启动开发服务时,并不会实际在demo文件夹下生成demo.bundle.js,打包好的文件是在内存中的,但并不影响我们使用。
下面是打包发布时所用的webpack配置,写在webpack.config.prod.js中
const path = require('path'); const merge = require('webpack-merge'); const baseConfig = require('./webpack.base.js'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 用于将组件的css打包成单独的文件输出到`dist`目录中 const devConfig = { entry: './src/index.js', mode: 'production', output: { path: path.resolve(__dirname, '../dist'), filename: 'index.js', // 输出文件 libraryTarget: 'umd', // 采用通用模块定义, 注意webpack到4.0为止依然不提供输出es module的方法,所以输出的结果必须使用npm安装到node_modules里再用,不然会报错 library: 'react-simple-component-boilerplate', // 库名称 libraryExport: 'default', // 兼容 ES6(ES2015) 的模块系统、CommonJS 和 AMD 模块规范 }, externals: { react: { root: "React", commonjs2: "react", commonjs: "react", amd: "react" }, "react-dom": { root: "ReactDOM", commonjs2: "react-dom", commonjs: "react-dom", amd: "react-dom" } }, module: { rules: [{ test: /\.(le|c)ss$/, use: [ MiniCssExtractPlugin.loader, "css-loader", { loader: "less-loader", options: { sourceMap: false } } ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: "main.min.css" // 提取后的css的文件名 }) ], } module.exports = merge(devConfig, baseConfig);
上面我们配置了externals字段,这一点非常重要。
externals定义了外部依赖。将react和react-dom添加进该字段,说明我们的组件将依赖外部的react和react-dom,这样就可以避免把react和react-dom打包进去(不然组件会很大)
4.1 配置babel
我们需要用babel把我们的代码编译成es5版本。在项目根目录新建一个.babelrc文件,输入以下内容。
{ "presets": [ [ "@babel/preset-env", { "targets": "> 0.25%, not dead" } ], "@babel/preset-react" ], "plugins": [ "@babel/plugin-transform-runtime", "@babel/plugin-transform-modules-commonjs", [ "@babel/plugin-proposal-decorators", { "legacy": true } ], "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread" ] }
我们在presets其中使用了preset-env, 规定了输出的代码目标环境是份额大于0.25%的浏览器。另外由于我们的项目里使用了react,presets中就要加入preset-react。
同时,plugins配置了一些babel插件,用于支持装饰器展开操作符等类内直接定义属性等新的es特性。
4.3 配置启动命令
我们再次回到项目根目录下的package.json中,编辑如下
"scripts": { "build": "set NODE_ENV=production && webpack --config ./config/webpack.config.prod.js", "pub": "npm run build && npm publish", "dev": "webpack-dev-server --config ./config/webpack.config.dev.js" }, "main": "dist/index.js", "files": ["dist"]
build 命令用于打包组件
dev 命令会使用webpack-dev-server启动一个开发服务用于预览组件效果
pub 命令进行打包组件并且发布到npm上
main字段指定了我们的组件的入口文件,files字段用于指定我们的npm包的文件目录。
5.试用和发布
要发布一个npm包,我们需使用如下命令添加一个npm的账号,如果已经添加过的这一步可以跳过。
npm adduser
如果已经有npm账号,可以使用npm login登陆。
如果不知道自己是否已经添加过了npm账号,使用npm whoami查看登陆信息即可
接下来就编辑package.json把组件的名称/版本/介绍等字段都填写一下。
好了,接下我们先使用npm run dev命令,此时会自动打开默认浏览器预览组件。
如果没什么问题的话,接下来使用npm run pub进行打包和发布。
等待发布完成后,我们就下载安装一下。
npm i your-component // 假设你的包名字叫your-component
使用自己发布的组件
import YourComponent from 'your-component'; import 'your-component/dist/main.min.css'; // 如果给组件写了样式,需要手动导入css文件
6.总结
到这里,一个非常非常简单的用于发布react小组件的脚手架就搭好了,总结一下其中要注意的地方:
webpack打包时libraryTarget要使用umd
externals 里要把外部依赖配置好
如果还要生成es module,可以额外使用gulp或rollup等工具
webpack4 之后建议使用MiniCssExtractPlugin来提取css