从零搭建React组件发布脚手架:Webpack配置与npm发布全流程

作者:编译时光

时间:2026-10-22

浏览:196

本文详细记录了从零搭建React组件发布脚手架的全过程。内容涵盖项目初始化、依赖安装、Webpack多环境配置(开发预览与生产发布)、Babel编译设置以及npm包发布命令。重点解析了externals外部依赖处理、UMD打包格式及webpack-dev-server的使用,帮助开发者快速建立可复用、易发布的组件工程模板。

文章目录

React组件脚手架搭建概述

近期公司内部部署了私有npm仓库,为此需要构建一个专门用于发布React组件的脚手架工具。在此过程中,我对Webpack的使用进行了再次梳理,现将脚手架的完整搭建过程分享如下。

我们期望该脚手架具备以下核心功能:

  • 在开发组件时支持实时预览效果。
  • 能够对组件涉及的各类资源(包括JS、CSS、图片等)进行统一打包处理。
  • 提供一键打包并发布的便捷操作。

项目初始化与目录结构

第一步:创建项目基础结构。

我们将脚手架命名为react-simple-component-boilerplate。。

首先,新建一个目录用于存放项目文件。


mkdir react-simple-component-boilerplate
cd react-simple-component-boilerplate

执行npm命令初始化项目。


npm init

随后系统会提示输入项目名称、版本号及作者等信息,也可直接回车跳过,后续再行修改。

完成上述步骤后,项目文件夹中将生成package.json文件,该文件用于存储项目及组件的各项元数据。

接下来,按照以下目录结构创建文件夹。


react-simple-component-boilerplate
 |-- config // webpack配置
 |-- demo // 开发时预览用
 |-- dist // 打包结果
 |-- src  // 源文件目录
  | -- assets // 存放图片等媒体文件
  | -- style // 存放样式,项目使用的是less来编写样式

依赖安装与组件编写

第二步:安装项目依赖。

由于目标是发布React组件,因此必须引入React相关依赖。

使用npm install命令安装以下依赖包。


npm install react react-dom --save

构建工具选用Webpack,同时需安装以下开发依赖。


 "devDependencies": {
 // babel用于将你写的es6+的代码转换到es5
 "@babel/cli": "^7.0.0",
 "@babel/core": "^7.0.0",
 "@babel/plugin-proposal-class-properties": "^7.0.0", // 用于支持class属性
 "@babel/plugin-proposal-decorators": "^7.0.0", // 支持decorator
 "@babel/plugin-transform-modules-commonjs": "^7.0.0",
 "@babel/plugin-transform-runtime": "^7.0.0", // 自动polyfill es5不支持的api特性
 "@babel/preset-env": "^7.0.0", // 根据目标环境来按需转码
 "@babel/preset-react": "^7.0.0", // 让babel支持react语法
 "babel-loader": "^8.0.0",
 "css-loader": "^1.0.0",
 "file-loader": "^2.0.0",
 "html-loader": "^0.4.4",
 "less-loader": "^4.1.0", // 使用less来编写样式
 "mini-css-extract-plugin": "^0.5.0", // 将css提取成一个单独的文件
 "style-loader": "^0.23.0",
 "webpack": "^4.26.0",
 "webpack-cli": "^3.1.2", // webpack4之后需要额外安装webpack-cli
 "webpack-dev-server": "^3.1.14", // 开发时预览组件所用的服务,在文件变化时会自动刷新页面
 "webpack-merge": "^4.1.4" // 用于合并webpack配置
 },

第三步:编写组件代码。

在/src目录下新建index.js文件,作为组件的入口文件。

若组件中包含图片、CSS等资源,请分别归类存放至assets和style文件夹中。

随后在index.js中编写一个简单的组件示例。


/* src/index.js */

import React from 'react';
import './style/style.less'; // 使用less的情况
import testPng from './assets/test.png'; // 使用图片的情况

export default class MyComponent extends Component {
 render(){
  return (<div>A new Component</div>)
 }
}

接着,在/demo目录下新建index.html和demo.js文件,用于开发阶段的组件效果预览。 index.html的内容如下:


<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<div id="root"></div>
<script src="demo.bundle.js"></script>
</body>
</html>

在demo.js中,我们需要引入刚才编写的组件(位于/src/index.js)以查看效果。开发过程中,demo.js会被打包生成demo.bundle.js,即index.html中引用的JS文件。


import React from 'react';
import ReactDom from 'react-dom';
import MyComponent from '../src/index'

const Demo = () => {
 return <div>
 <h1>组件预览:</h1>
 <MyComponent />
 </div>
}

ReactDom.render(<Demo />, document.getElementById('root'));

Webpack与Babel配置详解

第四步:配置Webpack和Babel。

4.1 配置Webpack。

在/config目录下创建三个Webpack配置文件。

  • webpack.base.js
  • webpack.config.dev.js(开发环境配置)。
  • webpack.config.prod.js(生产发布配置)。

鉴于开发与发布打包时存在部分公共且重复的配置,我们将这部分独立提取至webpack.base.js中。 以下是公共配置webpack.base.js的内容:


module.exports = {
 module: {
 rules: [
  { // 在webpack中使用babel需要babel-loader
  test: /\.js?$/,
  loader: 'babel-loader',
  exclude: '/node_modules/',
  },
  { // 用于加载组件或者css中使用的图片
  test: /\.(jpg|jpeg|png|gif|cur|ico|svg)$/,
  use: [{
   loader: 'file-loader', options: {
   name: "images/[name][hash:8].[ext]"
   }
  }]
  }
 ]
 }
}

以下是开发环境专用的Webpack配置,写入webpack.config.dev.js中。


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: '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-server启动开发服务时,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,从而避免将这两个库打包进组件内部(否则会导致组件体积过大)。

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包的文件目录。

npm发布流程与命令配置

第五步:试用与发布。

要发布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文件

关键配置总结

第六步:总结。

至此,一个极简的用于发布React小组件的脚手架搭建完毕,总结其中需注意的关键点:

  • Webpack打包时libraryTarget需设置为umd。
  • externals中需正确配置外部依赖。
  • 若需生成ES Module,可额外使用gulp或rollup等工具。
  • Webpack4之后建议使用MiniCssExtractPlugin来提取CSS。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章