react组件从搭建脚手架到在npm发布的步骤实现
最近公司给公司里架设了私有的npm仓库,相应地也需要一个用来发布react组件用的脚手架,在这个过程中又又又又复习了一下webpack,在这里分享下脚手架搭建的过程。
首先,我们预期的脚手架具有如下功能
- 开发组件时可以实时预览
- 对组件各种资源进行打包(js/css/图片等)
- 一键打包发布
1.创建项目
脚手架的名字暂时取react-simple-component-boilerplate。
首先创建一个新目录用于放我们的文件:
mkdirreact-simple-component-boilerplate cdreact-simple-component-boilerplate
使用npm命令创建一个项目
npminit
接下来会提示你输入项目的名称、版本号、作者等,也可以一路回车,稍后修改。
这一步完成后,你的项目文件夹里应该有一个package.json文件了,这个文件保存了我们项目和组件的各种信息。
接下来创建如下的目录结构
react-simple-component-boilerplate |--config//webpack配置 |--demo//开发时预览用 |--dist//打包结果 |--src//源文件目录 |--assets//存放图片等媒体文件 |--style//存放样式,项目使用的是less来编写样式
2.安装依赖
既然我们要发布的是react组件,那依赖里肯定少不了react。
使用npminstall安装下面的依赖
npminstallreactreact-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",//自动polyfilles5不支持的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配置 },
3.编写组件
在/src目录下新建一个index.js,这就是我们组件的入口文件了。
如果项目中要使用图片、css等,分类放到assets、style文件夹下就好。
下面我们就在index.js中写一个简单的组件
/*src/index.js*/ importReactfrom'react'; import'./style/style.less';//使用less的情况 importtestPngfrom'./assets/test.png';//使用图片的情况 exportdefaultclassMyComponentextendsComponent{ render(){ return(AnewComponent) } }
接下来,我们在/demo目录下新建index.html和demo.js这两个文件用于在开发组件时预览组件效果。
index.html内容如下
Title
在demo.js中,我们要使用一下刚刚写的组件(位于/src/index.js)看一下效果,开发中这个demo.js文件会被打包成demo.bundle.js,就是在上面index.html中引用的js。
importReactfrom'react'; importReactDomfrom'react-dom'; importMyComponentfrom'../src/index' constDemo=()=>{ return} ReactDom.render(组件预览:
,document.getElementById('root'));
4.配置webpack和babel
4.1配置webpack
在/config下我们建立三个webpack配置文件
- webpack.base.js
- webpack.config.dev.js//开发时的配置
- webpack.config.prod.js//打包发布时的配置
由于开发和发布打包时webpack的配置有一部分是公共而且重复的,我们把这部分的配置单独拿出来放到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中
constpath=require('path'); constmerge=require('webpack-merge'); constbaseConfig=require('./webpack.base.js');//引用公共的配置 constdevConfig={ 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-sevrer启动开发服务时,并不会实际在demo文件夹下生成demo.bundle.js,打包好的文件是在内存中的,但并不影响我们使用。
下面是打包发布时所用的webpack配置,写在webpack.config.prod.js中
constpath=require('path'); constmerge=require('webpack-merge'); constbaseConfig=require('./webpack.base.js'); constMiniCssExtractPlugin=require("mini-css-extract-plugin");//用于将组件的css打包成单独的文件输出到`dist`目录中 constdevConfig={ entry:'./src/index.js', mode:'production', output:{ path:path.resolve(__dirname,'../dist'), filename:'index.js',//输出文件 libraryTarget:'umd',//采用通用模块定义,注意webpack到4.0为止依然不提供输出esmodule的方法,所以输出的结果必须使用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:[ newMiniCssExtractPlugin({ 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%,notdead" } ], "@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":"setNODE_ENV=production&&webpack--config./config/webpack.config.prod.js", "pub":"npmrunbuild&&npmpublish", "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的账号,如果已经添加过的这一步可以跳过。
npmadduser
如果已经有npm账号,可以使用npmlogin登陆。
如果不知道自己是否已经添加过了npm账号,使用npmwhoami查看登陆信息即可
接下来就编辑package.json把组件的名称/版本/介绍等字段都填写一下。
好了,接下我们先使用npmrundev命令,此时会自动打开默认浏览器预览组件。
如果没什么问题的话,接下来使用npmrunpub进行打包和发布。
等待发布完成后,我们就下载安装一下。
npmiyour-component//假设你的包名字叫your-component
使用自己发布的组件
importYourComponentfrom'your-component'; import'your-component/dist/main.min.css';//如果给组件写了样式,需要手动导入css文件
6.总结
到这里,一个非常非常简单的用于发布react小组件的脚手架就搭好了,总结一下其中要注意的地方:
- webpack打包时libraryTarget要使用umd
- externals里要把外部依赖配置好
- 如果还要生成esmodule,可以额外使用gulp或rollup等工具
- webpack4之后建议使用MiniCssExtractPlugin来提取css
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。