溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

react組件從搭建腳手架到在npm發(fā)布的步驟實現(xiàn)

發(fā)布時間:2020-09-05 07:34:35 來源:腳本之家 閱讀:777 作者:JohnSnow 欄目:web開發(fā)

最近公司給公司里架設了私有的npm倉庫,相應地也需要一個用來發(fā)布react組件用的腳手架,在這個過程中又又又又復習了一下webpack,在這里分享下腳手架搭建的過程。

首先,我們預期的腳手架具有如下功能

  • 開發(fā)組件時可以實時預覽
  • 對組件各種資源進行打包(js/css/圖片等)
  • 一鍵打包發(fā)布

1.創(chuàng)建項目

腳手架的名字暫時取react-simple-component-boilerplate。

首先創(chuàng)建一個新目錄用于放我們的文件:

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

使用npm命令創(chuàng)建一個項目

npm init

接下來會提示你輸入項目的名稱、版本號、作者等,也可以一路回車,稍后修改。

這一步完成后,你的項目文件夾里應該有一個package.json文件了,這個文件保存了我們項目和組件的各種信息。

接下來創(chuàng)建如下的目錄結(jié)構(gòu)

react-simple-component-boilerplate
 |-- config // webpack配置
 |-- demo // 開發(fā)時預覽用
 |-- dist // 打包結(jié)果
 |-- src  // 源文件目錄
  | -- assets // 存放圖片等媒體文件
  | -- style // 存放樣式,項目使用的是less來編寫樣式

2.安裝依賴

既然我們要發(fā)布的是react組件,那依賴里肯定少不了react。

使用npm install安裝下面的依賴

npm install react react-dom --save

打包工具選擇的是webpack,下面是開發(fā)依賴,也需要一并安裝

 "devDependencies": {
 // babel用于將你寫的es6+的代碼轉(zhuǎn)換到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", // 根據(jù)目標環(huán)境來按需轉(zhuǎn)碼
 "@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", // 開發(fā)時預覽組件所用的服務,在文件變化時會自動刷新頁面
 "webpack-merge": "^4.1.4" // 用于合并webpack配置
 },

3.編寫組件

在/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這兩個文件用于在開發(fā)組件時預覽組件效果。
index.html內(nèi)容如下

<!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)看一下效果,開發(fā)中這個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>
 <h2>組件預覽:</h2>
 <MyComponent />
 </div>
}

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

4.配置webpack和babel

4.1 配置webpack

在/config下我們建立三個webpack配置文件

  • webpack.base.js
  • webpack.config.dev.js // 開發(fā)時的配置
  • webpack.config.prod.js // 打包發(fā)布時的配置

由于開發(fā)和發(fā)布打包時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]"
   }
  }]
  }
 ]
 }
}

下面是開發(fā)時所用的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', // 打包為開發(fā)模式
 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啟動開發(fā)服務時,并不會實際在demo文件夾下生成demo.bundle.js,打包好的文件是在內(nèi)存中的,但并不影響我們使用。

下面是打包發(fā)布時所用的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的方法,所以輸出的結(jié)果必須使用npm安裝到node_modules里再用,不然會報錯
 library: 'react-simple-component-boilerplate', // 庫名稱
 libraryExport: 'default', // 兼容 ES6(ES2015) 的模塊系統(tǒng)、CommonJS 和 AMD 模塊規(guī)范
 },
 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文件,輸入以下內(nèi)容。

{
 "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, 規(guī)定了輸出的代碼目標環(huán)境是份額大于0.25%的瀏覽器。另外由于我們的項目里使用了react,presets中就要加入preset-react。
同時,plugins配置了一些babel插件,用于支持裝飾器展開操作符等類內(nèi)直接定義屬性等新的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啟動一個開發(fā)服務用于預覽組件效果
  • pub 命令進行打包組件并且發(fā)布到npm上
  • main字段指定了我們的組件的入口文件,files字段用于指定我們的npm包的文件目錄。

5.試用和發(fā)布

要發(fā)布一個npm包,我們需使用如下命令添加一個npm的賬號,如果已經(jīng)添加過的這一步可以跳過。

npm adduser

如果已經(jīng)有npm賬號,可以使用npm login登陸。

如果不知道自己是否已經(jīng)添加過了npm賬號,使用npm whoami查看登陸信息即可

接下來就編輯package.json把組件的名稱/版本/介紹等字段都填寫一下。

好了,接下我們先使用npm run dev命令,此時會自動打開默認瀏覽器預覽組件。

如果沒什么問題的話,接下來使用npm run pub進行打包和發(fā)布。

等待發(fā)布完成后,我們就下載安裝一下。

npm i your-component // 假設你的包名字叫your-component

使用自己發(fā)布的組件

import YourComponent from 'your-component';
import 'your-component/dist/main.min.css'; // 如果給組件寫了樣式,需要手動導入css文件

6.總結(jié)

到這里,一個非常非常簡單的用于發(fā)布react小組件的腳手架就搭好了,總結(jié)一下其中要注意的地方:

  • webpack打包時libraryTarget要使用umd
  • externals 里要把外部依賴配置好
  • 如果還要生成es module,可以額外使用gulp或rollup等工具
  • webpack4 之后建議使用MiniCssExtractPlugin來提取css

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI