从搭建脚手架到在npm上发布react组件

最近公司给公司里架设了私有的npm仓库,相应地也需要一个用来发布react组件用的脚手架,在这个过程中又又又又复习了一下webpack,在这里分享下脚手架搭建的过程。

首先,我们预期的脚手架具有如下功能

  • 开发组件时可以实时预览
  • 对组件各种资源进行打包(js/css/图片等)
  • 一键打包发布

1.创建项目

脚手架的名字暂时取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来编写样式

2.安装依赖

既然我们要发布的是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配置},

3.编写组件

/src目录下新建一个index.js,这就是我们组件的入口文件了。
如果项目中要使用图片、css等,分类放到assetsstyle文件夹下就好。

下面我们就在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.htmldemo.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'));

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-loadertest: /\.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-servercontentBase: path.join(__dirname, '../demo'),compress: true,port: 9000, // 端口9000open: true // 自动打开浏览器},module: {rules: [{ // 编译lesstest: /\.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%的浏览器。另外由于我们的项目里使用了reactpresets中就要加入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

从搭建脚手架到在npm上发布react组件相关推荐

  1. TypeScript故事—如何使用TypeScript在NPM上发布自定义钩子

    On this page: 在本页面: What is NPM? 什么是NPM? Why React Custom Hooks? 为什么要使用自定义挂钩? Where does TypeScript ...

  2. 如何在npm上发布项目

    2019独角兽企业重金招聘Python工程师标准>>> 首先在https://www.npmjs.com 上注册一个账号 在本地创建一个项目 npm init 编写好项目代码 进入项 ...

  3. 使用cdn和npm引入的区别_在npm上发布自己的vue组件库(使用npm install 或者 CDN的方式引用)...

    一.npm publish 发布包到npm库的命令是npm publish npm publish发布包,需要先配置webpack.json文件,如果没有webpack.json文件,可以通过npm ...

  4. 如何在自己搭建的hexo博客上发布文章

    1.选择一款Markdown编译器编写文章(以下步骤以csdn为例): 2.编写文章:注册账号登录进去,点击:头像-管理博客,进入文章管理页面,点击左上角的"Markdown编辑器" ...

  5. 详细了解如何在npm上发布自己的包?

    大家好,我是纸飞机,想必大家都在项目中经常会使用npm install.yarn add.cnpm install等安装包的命令吧.那么大家好奇过,这些包都是怎么来的吗?不用迷茫,本篇文章就为你揭秘他 ...

  6. 从0到1,一步步开发React的loading组件,并发布到npm上

    没有发布过npm包的同学,可能会对NPM对开发有一种蜜汁敬畏,觉得这是一个很高大上的东西.甚至有次面试,面试官问我有没有发过npm包,当时只用过还没写过,我想应该挺难的,就小声说了没有,然后就让我回去 ...

  7. 如何使用@vue/cli 3.0在npm上创建,发布和使用你自己的Vue.js组件库

    译者按: 你可能npm人家的包过成千上万次,但你是否有创建,发布和使用过自己的npm包? 原文: How to create, publish and use your own VueJS Compo ...

  8. 华为 P40 或首发鸿蒙系统;新 iPhone Logo 移至中间;React 组件库 uiw 3.4.0 发布 | 极客头条​...

    快来收听极客头条音频版吧,智能播报由标贝科技提供技术支持. 「CSDN 极客头条」,是从 CSDN 网站延伸至官方微信公众号的特别栏目,专注于一天业界事报道.风里雨里,我们将每天为朋友们,播报最新鲜有 ...

  9. 使用yeoman搭建脚手架并发布到npm

    前言 最近主要在写前端的模板类项目,由于其中的webpack配置和引进数据注入ejs模板的方法大同小异,所以萌发出把该模板框架提取出来作为一个常用的脚手架,也方便以后同事可以进行复用. 之前在看< ...

最新文章

  1. 改变窗口背景_Illustrator实例教程:只需三步,利用画笔描边做出炫酷的背景
  2. NOIP2017游记
  3. 解决weblogic Managed Server启动非常慢的情况
  4. etal斜体吗 参考文献_参考文献类有关论文范例,与日语文提纲2016年,日语文提纲科目相关本科毕业论文范文...
  5. tensolrflow之基础变量
  6. vscode如何及时提示flutter代码
  7. SAP WebIDE Initialization process - 初始化逻辑分析
  8. python接口测试-项目实践(二)获取接口响应,取值(re、json)
  9. 创建和销毁对象(1)
  10. 使用 Shell 脚本实现安装进度指示器
  11. 《Java程序设计教程 实验手册》pdf 附下载链接
  12. 原生JS实现HTML文件上传,简单实现js上传文件功能
  13. 数学建模方法——斯皮尔曼相关系数及其显著性检验 (Spearman’s correlation coefficient for ranked data)
  14. html验证码 按住向右滑动,js实现滑动滑块验证登录
  15. 【mosek.fusion】Portfolio Optimization
  16. 百度翻译API使用简介
  17. 学生:无效文件.dsn问题
  18. 【观察】嘉诚信息:为智慧检务按下“加速键”
  19. cesium gltf 1.0 2.0的一些扩展
  20. 第三章 隐藏通信隧道技术

热门文章

  1. struts2官方 中文教程 系列一:创建一个struts2 web Application
  2. Mysql数据库主从及主主复制配置演示
  3. 基于蚁群算法的岸桥作业顺序研究
  4. 程序员永远不要再犯的5个编程错误
  5. centos7下的glusterfs的安装与使用
  6. GitLab公布关于开发者趋势的问卷调查结果
  7. memcached完全剖析系列教程《转》 memcached完全剖析系列教程–2.理解memcached的内存存储...
  8. 巧用Windows server 2008密码重置盘
  9. hp 服务器系统无法启动不了怎么办,HP Elite X2 1011 G1 笔记本电脑 - 电脑无法启动至预启动执行环境...
  10. babyos (三)——利用BIOS INT 0x13读取软盘