教程:使用umd、commonjs和es三种模式制作自己的React 组件(库)

2019-08-16 admin

创建 package.json 文件

执行命令npm init创建 package.json 文件,一步步输入你自己的组件基本信息,下面是我创建的

{
  "name": "react-code-previewer",
  "version": "0.0.1",
  "description": "基于 react 和 antd 的代码预览器组件",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+ssh://git@github.com/zhangwei900808/react-code-previewer.git"
  },
  "keywords": [
    "react",
    "antd",
    "code-preview"
  ],
  "author": "zhangwei",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/zhangwei900808/react-code-previewer/issues"
  },
  "homepage": "https://github.com/zhangwei900808/react-code-previewer#readme"
}

初始化组件

首先在项目目录下创建相应文件夹和基本配置文件,目录结构如下所示:

|-- com.github
    |-- .editorconfig
    |-- .gitignore
    |-- .npmignore
    |-- LICENSE
    |-- package.json
    |-- .react-code-previewer
    |-- components
    |   |-- index.js
    |   |-- code-previewer
    |       |-- index.js
    |       |-- style
    |           |-- index.js
    |           |-- index.scss
    |-- src

创建好之后,我们开始制作该组件,在目录 code-previewer/index.js 添加代码,如下所示:

import React, { Component } from "react";

class CodePreviewer extends Component {
  render() {
    <div className="code-preview-container">
      <div className="cp-component">
        <div className="component-header">header</div>
        <div className="component-content">content</div>
        <div className="component-footer">footer</div>
      </div>
      <div className="cp-code">
        <div className="code-header">code header</div>
        <div className="code-tabs">code tabs</div>
        <div className="code-content">code content</div>
      </div>
    </div>;
  }
}

export default CodePreviewer;

在目录 code-previewer/style/index.js 添加代码,如下所示:

import "./index.scss";

在目录 code-previewer/style/index.scss 添加代码,如下所示:

.code-preview-container {
  .cp-component {
    .component-header {}
    .component-content {}
    .component-footer {}
  }
  .cp-code {
    .code-header {}
    .code-tabs {}
    .code-content {}
  }
}

我们现在已经初始化组件内容,虽然很简单,后面我们再优化,现在我们要对外暴露该组件,所以我们在目录 /components/index.js 添加代码,如下:

import CodePreview from "./code-previewer";

export { CodePreview };
export default { CodePreview };

umd 打包

首先我们在目录创建.react-code-preview/webpack.config.umd.js 文件,并添加如下代码:

const fs = require("fs");
const path = require("path");
const webpack = require("webpack");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const nodeExternals = require("webpack-node-externals");
const WebpackMd5Hash = require("webpack-md5-hash");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

const resolve = dir => path.join(__dirname, ".", dir);
const isProd = process.env.NODE_ENV === "production";
const { version, name, description } = require("../package.json");
const distDir = path.join(process.cwd(), "dist");

module.exports = {
  mode: "production",
  entry: { [name]: "./components/index.js" },
  output: {
    path: distDir,
    filename: "[name].min.js",
    // 采用通用模块定义
    libraryTarget: "umd",
    library: name
  },
  devtool: "#source-map",
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              sourceMap: true
            }
          },
          {
            loader: "sass-loader",
            options: {
              sourceMap: true
            }
          }
        ]
      }
    ]
  },
  resolve: {
    enforceExtension: false,
    extensions: [".js", ".jsx", ".json", ".less", ".css"]
  },
  // 注意:本地预览的时候要注释,否则报 require undefined
  // https://stackoverflow.com/questions/45818937/webpack-uncaught-referenceerror-require-is-not-defined
  externals: [nodeExternals()],
  plugins: [
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: [distDir]
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css"
    }),
    new WebpackMd5Hash(),
    new webpack.BannerPlugin(` \n ${name} v${version} \n ${description} ${fs.readFileSync(path.join(process.cwd(), "LICENSE"))}`)
  ],
  //压缩js
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: "styles",
          test: /\.scss$/,
          chunks: "all",
          enforce: true
        }
      }
    },
    minimizer: [
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        sourceMap: true
      }),
      new OptimizeCssAssetsPlugin({
        assetNameRegExp: /\.css\.*(?!.*map)/g, //注意不要写成 /\.css$/g
        cssProcessor: require("cssnano"),
        cssProcessorOptions: {
          discardComments: { removeAll: true },
          safe: true,
          autoprefixer: false
        },
        canPrint: true
      })
    ]
  },
  node: {
    setImmediate: false,
    dgram: "empty",
    fs: "empty",
    net: "empty",
    tls: "empty",
    child_process: "empty"
  }
};

在目录根目录下创建 .babelrc 文件,并添加如下代码:

{
  "presets": [
    ["@babel/preset-env", {
      "modules": false,
    }], "@babel/preset-react"
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "useESModules": false
    }]
  ]
}

创建完成之后添加依赖包,并修改 package.json 文件,如下:

"scripts": {
    "build:umd": "webpack --mode production --config .react-code-previewer/webpack.config.umd.js"
  },
"devDependencies": {
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/plugin-transform-runtime": "^7.5.5",
    "@babel/preset-env": "^7.5.5",
    "@babel/preset-react": "^7.0.0",
    "@babel/runtime": "^7.5.5",
    "babel-loader": "^8.0.6",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.2.0",
    "fs": "^0.0.1-security",
    "mini-css-extract-plugin": "^0.8.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "path": "^0.12.7",
    "react": "^16.9.0",
    "sass-loader": "^7.2.0",
    "style-loader": "^1.0.0",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "webpack": "^4.39.2",
    "webpack-cli": "^3.3.6",
    "webpack-node-externals": "^1.7.2"
  }

添加完成之后,执行命令打包

yarn build:umd

clipboard.png

clipboard.png

成功在 dist 目录下创建好了打包后的.js文件,目录如下所示:

|-- com.github
    |-- .babelrc
    |-- .editorconfig
    |-- .gitignore
    |-- .npmignore
    |-- LICENSE
    |-- directoryList.md
    |-- package.json
    |-- yarn.lock
    |-- .react-code-previewer
    |   |-- webpack.config.umd.js
    |-- components
    |   |-- index.js
    |   |-- code-previewer
    |       |-- index.js
    |       |-- style
    |           |-- index.js
    |           |-- index.scss
    |-- dist
    |   |-- react-code-previewer.min.js
    |   |-- react-code-previewer.min.js.map
    |-- src

注意:因为后面组件会使用 bable-plugins-import 按需加载组件,所以上面的组件并没有直接引用.scss文件,这样也就不会在 dist 文件夹下打包.css文件了,但是.css 文件一定要有,后面会讲gulp如何打包.css文件

commonjs 打包

上面讲了如何使用webpack.config.umd.js 的 umd 模式打包 react 组件,接下来我们讲如何使用 commonjs 模式打包 react 组件,commonjs 模式打包我们使用的是 babel 直接打包,并且要修改.babelrc 和 package.json,如下:

.babelrc

{
  "presets": [
    ["@babel/env", {
      "loose": true,
      "modules": "cjs"
    }], "@babel/preset-react"
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "useESModules": false
    }],
  ]
}

package.json

"build:commonjs": "babel components -d lib --source-maps"

添加完成之后,执行命令打包

yarn build:commonjs

clipboard.png

clipboard.png

|-- com.github
    |-- .babelrc
    |-- .editorconfig
    |-- .gitignore
    |-- .npmignore
    |-- LICENSE
    |-- directoryList.md
    |-- package.json
    |-- yarn.lock
    |-- .react-code-previewer
    |   |-- webpack.config.umd.js
    |-- components
    |   |-- index.js
    |   |-- code-previewer
    |       |-- index.js
    |       |-- style
    |           |-- index.js
    |           |-- index.scss
    |-- dist
    |   |-- react-code-previewer.min.js
    |   |-- react-code-previewer.min.js.map
    |-- lib
    |   |-- index.js
    |   |-- index.js.map
    |   |-- code-previewer
    |       |-- index.js
    |       |-- index.js.map
    |       |-- style
    |           |-- index.js
    |           |-- index.js.map
    |-- src

es modules 打包

es modules打包和 babel 打包很类似也是通过 babel 打包,不同的是.babelrc 文件有所修改,代码如下: .babelrc

{
  "presets": [
    ["@babel/env", {
      "loose": true,
      "modules": false
    }], "@babel/preset-react"
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "useESModules": true
    }]
  ]
}

package.json

"build:es": "babel components -d es --source-maps"
添加完成之后,执行命令打包

yarn build:es


![clipboard.png](/img/bVbwtk0)

![clipboard.png](/img/bVbwtlf)

|-- react-code-previewer

|-- .babelrc
|-- .editorconfig
|-- .gitignore
|-- .npmignore
|-- LICENSE
|-- package.json
|-- yarn.lock
|-- .react-code-previewer
|   |-- webpack.config.umd.js
|-- components
|   |-- index.js
|   |-- code-previewer
|       |-- index.js
|       |-- style
|           |-- index.js
|           |-- index.scss
|-- dist
|   |-- react-code-previewer.min.js
|   |-- react-code-previewer.min.js.map
|-- es
|   |-- index.js
|   |-- index.js.map
|   |-- code-previewer
|       |-- index.js
|       |-- index.js.map
|       |-- style
|           |-- index.js
|           |-- index.js.map
|-- lib
|   |-- index.js
|   |-- index.js.map
|   |-- code-previewer
|       |-- index.js
|       |-- index.js.map
|       |-- style
|           |-- index.js
|           |-- index.js.map
|-- src


这样就完成了 umd、commonjs 和 es 的三种打包方式,但是这样有个问题:每次打包都要修改.babelrc 文件,能不能直接通过一条命令打包三种模式的方法呢?下面我们就来讲讲。

## 组合三种打包模式
通过三种打包模式我们发现,.babelrc 文件跟三种模式打包有关,尤其是其中几个对象的设置,如:loose、modules 和 useESModules,其它的设置都一样,所以我们可以使用cross-env BABEL_ENV=umd(commonjs 或者 es)增加 BABEL_ENV 环境变量进行判断。还有,.babelrc 文件我们要换成.babelrc.js,因为前者不能使用 js 语法,这里[有篇文章](https://www.babeljs.cn/docs/configuration)很好的分析.babelrc、.babelrc.js 和 babel.config.js文件之间的区别

## gulp 打包 css

## 组件按需加载

## 发布组件到 npm

## 发布组件到 github pages

## 使用组件

## 总结
1、js sourcemap
2、css sourcemap

[转载]原文链接:https://segmentfault.com/a/1190000020093455

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-72681.html

文章标题:教程:使用umd、commonjs和es三种模式制作自己的React 组件(库)

相关文章
vue 数组遍历方法forEach和map的原理解析和实际应用
一、前言 forEach和map是数组的两个方法,作用都是遍历数组。在vue项目的处理数据中经常会用到,这里介绍一下两者的区别和具体用法示例。 二、代码 1. 相同点 都是数组的方法 都用来遍历数组 两个函数都有4个参数:匿名函数中可传3...
2018-11-15
html5+JavaScript教程-微信打飞机小游戏源码
js &#x2F;&#x2F; JavaScript Document var c = document.getElementById(&quot;dotu&quot;); var cxt = c.getContext(&quot;2d&q...
2015-11-12
js性能优化 如何更快速加载你的JavaScript页面
确保代码尽量简洁 不要什么都依赖JavaScript。不要编写重复性的脚本。要把JavaScript当作糖果工具,只是起到美化作用。别给你的网站添加大量的JavaScript代码。只有必要的时候用一下。只有确实能改善用户体验的时候用一下。 ...
2015-11-12
10个强大的纯CSS3动画案例分享
我们的网页外观主要由CSS控制,编写CSS代码可以任意改变我们的网页布局以及网页内容的样式。CSS3的出现,更是可以让网页增添了不少动画元素,让我们的网页变得更加生动有趣,并且更易于交互。本文分享了10个非常炫酷的CSS3动画案例,希望大家...
2015-11-16
2015年JavaScript或“亲库而远框架”
2014年过去了,作为一个JavaScript开发者很难满怀信心的去“挽回”一个特定的库或技术,即便是强大的Angular,似乎也因为最近的一些事情而动摇。 2014年10月的ng-europe会议上,Angular开发者团队透露了一个关于...
2015-11-12
JavaScript实现PC手机端和嵌入式滑动拼图验证码三种效果
PC和手机端网站滑动拼图验证码效果源码,同时包涵了弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值,嵌入式Demo,使用表单形式提交二次验证所需的验证结果值,移动端手动实现弹出式Demo三种效果 首先要确认前端使用页面,比如...
2017-03-17
v-charts | 饿了么团队开源的基于 Vue 和 ECharts 的图表工具
在使用echarts生成图表时,经常需要做繁琐的数据类型转化、修改复杂的配置项,v-charts的出现正是为了解决这个 痛点。基于Vue2.0和echarts封装的v-charts图表组件,只需要统一提供一种对前后端都友好的数据格式 设置简...
2018-05-24
Angular2-primeNG文件上传模块FileUpload使用详解
近期在学习使用Angular2做小项目,期间用到很多primeNG的模块。 本系列将结合实战总结angular2-primeNG各个模块的使用经验。 文件上传模块FileUploadModule 首先要在使用该组件的模块内导入文件上传模块 ...
2017-03-09
Vue获取DOM元素样式和样式更改示例
在 vue 中用 document 获取 dom 节点进行节点样式更改的时候有可能会出现 ‘style’ is not definde的错误,这时候可以在 mounted 里用 $refs 来获取样式,并进行更改: &lt;template...
2017-03-13
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: &lt;!DOCTYPE html&gt; &lt;html lang=&quot;en&quot;&gt; &lt;head&gt; ...
2017-03-13
回到顶部