创建 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() {

return (

header
content
footer

code header
code tabs
code content

);

}

}

export default CodePreviewer;

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

import "./index.scss";

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

.code-preview-container {

.cp-component {

.component-header {

color: red;

}

.component-content {

color: green;

}

.component-footer {

color: yellow;

}

}

.cp-code {

.code-header {

color: red;

}

.code-tabs {

color: green;

}

.code-content {

color: yellow;

}

}

}

我们现在已经初始化组件内容,虽然很简单,后面我们再优化,现在我们要对外暴露该组件,所以我们在目录 /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

成功在 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

|-- 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

|-- 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 语法,这里有篇文章很好的分析.babelrc、.babelrc.js 和 babel.config.js文件之间的区别。代码如下:

.babelrc.js

let babel_env = process.env["BABEL_ENV"];

let loose = false,

modules = false,

useESModules = false;

switch (babel_env) {

case "commonjs":

loose = true;

modules = "cjs";

useESModules = false;

break;

case "es":

loose = true;

modules = false;

useESModules = true;

break;

case "umd":

loose = false;

modules = false;

useESModules = false;

break;

}

const presets = [["@babel/preset-env", { loose, modules }], "@babel/preset-react"];

const plugins = ["@babel/plugin-proposal-object-rest-spread", ["@babel/plugin-transform-runtime", { useESModules }]];

module.exports = { presets, plugins };

另外要注意的一点是,每次打包最好把之前的 dist、lib、es 目录删除防止相互干扰,删除目录我们使用 rimraf 包,如下:

package.json

"build:umd": "cross-env BABEL_ENV=umd webpack --mode production --config .react-code-previewer/webpack.config.umd.js",

"build:commonjs": "rimraf lib && cross-env BABEL_ENV=commonjs babel components -d lib --source-maps",

"build:es": "rimraf es && cross-env BABEL_ENV=es babel components -d es --source-maps"

注意:因为 umd 是通过 webpack.config.umd.js 打包的所以我们直接在该文件中删除 dist 文件夹

plugins: [

new CleanWebpackPlugin({

cleanOnceBeforeBuildPatterns: [path.join(process.cwd(), "dist")]

})

]

设置好之后,我们分别打包一下,如下所示:

三种打包模式都成功打包成 dist、es 和 lib 文件夹中,虽然都成功了但是每次执行三条命令非常麻烦,如何通过一条命令打包三种模式呢,其实也很简单,代码如下:

package.json

"scripts": {

"build:all": "yarn build:umd && yarn build:commonjs && yarn build:es"

},

这样我们只要执行 yarn build:all 命令三种模式下的打包都能完成,非常方便。

gulp 打包 css

好了,到了这里心急的小伙伴一定要说,你把 js都打包好了,那 css呢?现在我们就来处理 css 打包,首先我们创建 gulpfile.js文件,代码如下:

const fs = require("fs");

const gulp = require("gulp");

const path = require("path");

const cleanCSS = require("gulp-clean-css");

const rename = require("gulp-rename");

const concat = require("gulp-concat");

const replace = require("gulp-replace");

const sass = require("gulp-sass");

const sourcemaps = require("gulp-sourcemaps");

const autoprefixer = require("gulp-autoprefixer");

const size = require("gulp-filesize");

const { name } = require("../package.json");

const resolve = dir => path.join(__dirname, ".", dir);

const distDir = resolve("../dist");

const libDir = resolve("../lib");

const esDir = resolve("../es");

const sassDir = resolve("../components/**/*.scss");

const indexJsDir = resolve("../components/**/style/index.js");

// 复制 sass 文件到 lib es 文件夹下

gulp.task("copy-sass", () => {

return gulp

.src(sassDir)

.pipe(sourcemaps.init())

.pipe(sourcemaps.write("."))

.pipe(gulp.dest(libDir))

.pipe(gulp.dest(esDir));

});

// 根据 index.js 创建一个全新的 css.js 供按需加载 styel:'css' 使用

gulp.task("replace-indexjs", () => {

return gulp

.src(indexJsDir)

.pipe(sourcemaps.init())

.pipe(replace("scss", "css"))

.pipe(

rename(function(path) {

path.basename = "css";

path.extname = ".js";

})

)

.pipe(sourcemaps.write("."))

.pipe(gulp.dest(libDir))

.pipe(gulp.dest(esDir));

});

// 编译 sass 文件到 es 和 lib 文件夹下

gulp.task("compile-sass", () => {

return gulp

.src(sassDir)

.pipe(sourcemaps.init())

.pipe(sass())

.pipe(autoprefixer())

.pipe(cleanCSS())

.pipe(sourcemaps.write("."))

.pipe(gulp.dest(libDir))

.pipe(gulp.dest(esDir));

});

// 编译 sass 到 dist 文件夹下

gulp.task("dist-css", () => {

return gulp

.src(sassDir)

.pipe(sourcemaps.init())

.pipe(sass())

.pipe(autoprefixer())

.pipe(concat(`${name}.css`))

.pipe(size())

.pipe(sourcemaps.write("."))

.pipe(gulp.dest(distDir))

.pipe(concat(`${name}.min.css`))

.pipe(size())

.pipe(cleanCSS())

.pipe(sourcemaps.write("."))

.pipe(gulp.dest(distDir));

});

gulp.task("compile", gulp.series(gulp.parallel("copy-sass", "replace-indexjs", "compile-sass", "dist-css")));

package.json

"scripts": {

"build:css": "cd .react-code-previewer && gulp compile",

"build:umd": "cross-env BABEL_ENV=umd webpack --mode production --config .react-code-previewer/webpack.config.umd.js",

"build:commonjs": "rimraf lib && cross-env BABEL_ENV=commonjs babel components -d lib --source-maps",

"build:es": "rimraf es && cross-env BABEL_ENV=es babel components -d es --source-maps",

"build:all": "yarn build:umd && yarn build:commonjs && yarn build:es"

},

"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",

"cross-env": "^5.2.0",

"css-loader": "^3.2.0",

"fs": "^0.0.1-security",

"gulp": "^4.0.2",

"gulp-autoprefixer": "^6.1.0",

"gulp-clean-css": "^4.2.0",

"gulp-concat": "^2.6.1",

"gulp-filesize": "^0.0.6",

"gulp-rename": "^1.4.0",

"gulp-replace": "^1.0.0",

"gulp-sass": "^4.0.2",

"gulp-sourcemaps": "^2.6.5",

"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"

}

修改好了我们执行命令打包 css:

yarn build:css

这样我们就完成了 js 的三种模式和 css 的打包,不要忘了把 build:css也放到 build:all 命令里面,如下:

"build:all": "yarn build:umd && yarn build:commonjs && yarn build:es && yarn build:css"

接下来我们会提交到 github以及发布到 npm。

提交代码到 github

我们在 github上面创建一个新项目:react-code-previewer,然后在本地代码执行 如下 git 命令:

git init

git remote add origin git@github.com:zhangwei900808/react-code-previewer.git

git add .

git commit -am 'your-commit-msg'

git push -u origin master

发布组件到 npm

完成了组件制作之后我们就可以发布到 npm 其他人也就可以直接通过 npm install 你的插件了。

注册一个 npm 账号

npm login

npm version your-package-version

npm publish

注意:发布到 npm 的时候 npm 源要设置成官方的

npm set registry http://registry.npmjs.org

使用组件并按需加载 css 样式

在你的另外的 react项目中我们添加刚上传的包:

yarn add react-code-previewer

import { CodePreviewer } from "react-code-previewer";

.babelrc

{

"presets": ["@babel/preset-env", "@babel/preset-react"],

"plugins": [

[

"import",

{

"libraryName": "react-code-previewer",

"libraryDirectory": "lib",

"style": "css"

}

]

]

}

按需加载我们使用的是 antd 提供的babel-plugin-import插件,这里要注意的是 style 属性:

style: true 表示从style/index.scss 加载样式

style: 'css' 表示从 style/index.css 加载样式

完善组件代码

上面虽然写了一个react-code-previewer组件,但是里面没内容,主要是演示三种模式下打包和 css 打包,好了,现在我们来完善下这个组件,并发布到 github pages预览效果。

本地预览(离线)

代码都完成之后,我们要在本地看看效果,首先添加webpack.config.dev.js文件,需要注意的是.dev.js和.umd.js文件相差不大.dev.js文件少了output多了HtmlWebpackPlugin配置,代码如下:

const fs = require("fs");

const path = require("path");

const webpack = require("webpack");

const TerserPlugin = require("terser-webpack-plugin");

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");

const nodeExternals = require("webpack-node-externals");

const HtmlWebpackPlugin = require("html-webpack-plugin");

const { CleanWebpackPlugin } = require("clean-webpack-plugin");

const postcssPresetEnv = require("postcss-preset-env");

const resolve = dir => path.join(__dirname, ".", dir);

const isProd = process.env.NODE_ENV === "production";

const { version, name, description } = require("../package.json");

const docsDir = path.join(process.cwd(), "docs");

module.exports = {

mode: "development",

entry: { [name]: "./src/index.js" },

// output: {

// // path: resolve("dist"), // 输出目录

// path: docsDir,

// filename: "static/js/[name].min.js",

// chunkFilename: "static/js/[name].chunk.js",

// umdNamedDefine: true, // 是否将模块名称作为 AMD 输出的命名空间

// //不加下面几行,被引用会被报错

// libraryTarget: "umd", // 采用通用模块定义

// library: [name]

// },

devtool: "#source-map",

module: {

rules: [

{

test: /\.md$/,

use: "raw-loader"

},

{

test: /\.(js|jsx)$/,

exclude: /node_modules/,

use: {

loader: "babel-loader"

}

},

{

test: /\.(pc|sc|c)ss$/,

use: [

// fallback to style-loader in development

{

loader: "style-loader"

},

{

loader: "css-loader",

options: {

sourceMap: true,

importLoaders: 1

}

},

{

loader: "postcss-loader",

options: {

ident: "postcss",

sourceMap: true,

plugins: () => [

postcssPresetEnv({

stage: 3,

features: {

"custom-properties": true,

"nesting-rules": true

},

browsers: "last 2 versions"

})

]

}

}

]

},

{

test: /\.(jpe?g|png|gif|ogg|mp3)$/,

use: [

{

loader: "url-loader",

options: {

limit: 10 * 1000

}

}

]

},

{

test: /\.(woff|svg|eot|ttf)\??.*$/,

use: ["file-loader"]

}

]

},

resolve: {

enforceExtension: false,

extensions: [".js", ".jsx", ".json", ".less", ".css"]

},

plugins: [

new MiniCssExtractPlugin({

filename: "static/css/[name].min.css",

chunkFilename: "static/css/[name].chunk.css"

}),

//预览

new HtmlWebpackPlugin({

template: path.join(__dirname, "../public/index.html"), //指定要打包的html路径和文件名

filename: "./index.html" //指定输出路径和文件名

}),

new webpack.HotModuleReplacementPlugin(),

new webpack.NamedModulesPlugin(),

new webpack.NoEmitOnErrorsPlugin()

],

//压缩js

optimization: {

minimizer: [

new TerserPlugin({

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

})

]

}

};

现在我们修改下.babelrc.js使其能够支持ant-design

// 预览情况下添加对 antd 按需加载样式的支持

if (babel_env === "preview") {

plugins.push([

"import",

{

libraryName: "antd",

libraryDirectory: "es",

style: "css" // `style: true` 会加载 less 文件

},

"ant-design"

]);

}

这样我们再修改下package.json就可以本地预览了,代码如下:

"start": "cross-env BABEL_ENV=preview webpack-dev-server --port 3002 --open --config scripts/webpack.config.dev.js",

执行命令yarn start即可预览

在线预览(github pages)

1、安装gh-pages

yarn add gh-pages

2、添加webpack.config.prod.js文件,.prod.js比.umd.js文件多了个HtmlWebpackPlugin的配置其他的没有太大变化,代码如下:

const path = require("path");

const webpack = require("webpack");

const TerserPlugin = require("terser-webpack-plugin");

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");

const nodeExternals = require("webpack-node-externals");

const HtmlWebpackPlugin = require("html-webpack-plugin");

const InlineManifestWebpackPlugin = require("inline-manifest-webpack-plugin");

const HtmlWebpackInlineSourcePlugin = require("html-webpack-inline-source-plugin");

const { CleanWebpackPlugin } = require("clean-webpack-plugin");

const { version, name, description } = require("../package.json");

const postcssPresetEnv = require("postcss-preset-env");

const resolve = dir => path.join(__dirname, ".", dir);

const isProd = process.env.NODE_ENV === "production";

const docsDir = path.join(process.cwd(), "docs");

module.exports = {

mode: "production",

// 预览

entry: { main: "./src/index.js" },

output: {

// path: resolve("dist"), // 输出目录

path: docsDir,

filename: "static/js/[name].min.js",

chunkFilename: "static/js/[name].chunk.js",

umdNamedDefine: true, // 是否将模块名称作为 AMD 输出的命名空间

//不加下面几行,被引用会被报错

libraryTarget: "umd", // 采用通用模块定义

library: [name]

},

devtool: "#source-map",

module: {

rules: [

{

test: /\.md$/,

use: "raw-loader"

},

{

test: /\.(pc|le|sc|c)ss$/,

use: [

MiniCssExtractPlugin.loader,

{

loader: "css-loader",

options: { importLoaders: 1, sourceMap: true }

},

{

loader: "postcss-loader",

options: {

ident: "postcss",

sourceMap: true,

plugins: () => [

postcssPresetEnv({

stage: 3,

features: {

"custom-properties": true,

"nesting-rules": true

},

browsers: "last 2 versions"

})

]

}

}

]

},

{

test: /\.(js|jsx)$/,

exclude: /node_modules/,

use: {

loader: "babel-loader"

}

},

{

test: /\.(jpe?g|png|gif|ogg|mp3)$/,

use: [

{

loader: "url-loader",

options: {

limit: 10 * 1000

}

}

]

}

]

},

resolve: {

extensions: [".js", ".jsx"]

},

plugins: [

new CleanWebpackPlugin({

cleanOnceBeforeBuildPatterns: [docsDir]

}),

new MiniCssExtractPlugin({

filename: "static/css/[name].min.css",

chunkFilename: "static/css/[name].chunk.css"

}),

//预览

new HtmlWebpackPlugin({

//指定要打包的html路径和文件名

template: path.join(__dirname, "../public/index.html"),

//指定输出路径和文件名

filename: "./index.html"

}),

new InlineManifestWebpackPlugin(),

new HtmlWebpackInlineSourcePlugin(),

new webpack.HotModuleReplacementPlugin(),

new webpack.NamedModulesPlugin(),

new webpack.NoEmitOnErrorsPlugin()

],

//压缩js

optimization: {

splitChunks: {

cacheGroups: {

vendors: {

test: /[\\/]node_modules[\\/]/,

name: "vendors",

minSize: 30000,

minChunks: 1,

chunks: "initial",

priority: 1 // 该配置项是设置处理的优先级,数值越大越优先处理

},

commons: {

test: /[\\/]src[\\/]common[\\/]/,

name: "commons",

minSize: 30000,

minChunks: 3,

chunks: "initial",

priority: -1,

reuseExistingChunk: true // 这个配置允许我们使用已经存在的代码块

}

}

},

// 生成运行时.js 文件,并写入到.html

runtimeChunk: "single",

minimizer: [

new TerserPlugin({ cache: true, parallel: true, sourceMap: true }),

new OptimizeCssAssetsPlugin({

assetNameRegExp: /\.css\.*(?!.*map)/g, //注意不要写成 /\.css$/g

cssProcessor: require("cssnano"),

cssProcessorOptions: {

//生成.css.map 文件

map: true,

discardComments: { removeAll: true },

// 避免 cssnano 重新计算 z-index

safe: true,

// 关闭autoprefixer功能

// 使用postcss cssnano的autoprefixer功能

autoprefixer: false

},

canPrint: true

})

]

}

};

2、配置package.json

"build:prod": "cross-env BABEL_ENV=preview webpack --mode production --config scripts/webpack.config.prod.js",

"deploy:docs": "yarn build:prod && gh-pages -d docs"

执行yarn deploy:docs即可编译预览代码到build文件夹,然后gh-pages创建gh-pages分支到github,然后我们到github设置gh-pages为github pages即可,这样就完成了在线预览了。

总结

1、三种打包方式的不同umd、commonjs和es modules,所修改的webpack文件和对应的bable.js文件的区别,理解和总结之后以后可以用相同的方法打造自己的组件库。

2、js sourcemap使用--source-maps生成,css sourcemap使用生成

const sourcemaps = require("gulp-sourcemaps");

...

.pipe(sourcemaps.init())

.pipe(sourcemaps.write("."))

...

3、gulp可以对png的打包支持

const imgDir = resolve("../components/**/*.png");

// 复制 img 文件到 lib es 文件夹下

gulp.task("copy-img", () => {

return gulp

.src(imgDir)

.pipe(gulp.dest(libDir))

.pipe(gulp.dest(esDir));

});

4、webpack4和babel7跟之前版本有所区别,如webpack4有optimization属性,babel7使用的包是@babel开头等等

5、如果你想使用自己的域名,那么你要在public里面添加 CNAME 文件,然后添加yarn add copy-webpack-plugin插件,再修改plugins属性new CopyPlugin([{ from: "./public/CNAME", to: "." }])即可,作用就是把CNAME文件从public打包到build文件夹下,这样发布到github pages之后就会被其识别就可以访问了。

6、404

7、github pages history模式

参考

html5读取umd,教程:使用umd、commonjs和es三种模式制作自己的React 组件(库)相关推荐

  1. java浮点数化为整数_[Java教程]javascript浮点数转换成整数三种方法

    [Java教程]javascript浮点数转换成整数三种方法 0 2014-06-24 04:00:27 将浮点数转换成整数方法有很多,分享三种常用方法. Summary 暂时我就想到3个方法而已.如 ...

  2. ps自定义形状工具_PS教程——用PS绘制虚线的三种方法

    点线面是平面构成的基本元素,而线条在平面设计中亦有规整分割版面.装饰造型的作用,能大幅提升版面的可读性.学会用PS绘制线条是每个自学平面设计初学者的基本功,本篇平面设计学习日记, @酷coo豆一孔之见 ...

  3. 前端React教程第三课 数据是如何在 React 组件之间流动

    04 数据是如何在 React 组件之间流动的?(上) 通过前面 3 个课时的学习,相信你已经对 React 生命周期相关的"Why""What"和" ...

  4. 读取.bin激光雷达点云文件格式并可视化三种的方法

    申明:从KITTI官网下载到的激光雷达点云数据为.bin格式,为此找到了三种方法,现在分享出来大家一起讨论. 程序运行环境 运行测试系统:Ubuntu16.04 运行环境:python3.6 方法一: ...

  5. spark读取csv转化为rdd(python+scala+java三种代码汇总)

    --------------------------------------------------------------------基本信息---------------------------- ...

  6. 读取html tr td,获取tr td 的三种方式

    /* 第一种,原生的js,先获取table然后获取tr标签,然后遍历td *///      $('#selectIds').val("");//       var table  ...

  7. 一文把Redis主从复制、哨兵、Cluster三种模式摸透,kalilinux使用教程书

    默认如果开启RDB快照(至少一条save指令)并且最新的后台保存失败,Redis将会停止接受写操作 这将使用户知道数据没有正确的持久化到硬盘,否则可能没人注意到并且造成一些灾难 stop-writes ...

  8. [js高手之路] html5 canvas系列教程 - 线条样式(lineWidth,lineCap,lineJoin,setLineDash)

    上文,写完弧度与贝塞尔曲线[js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具),本文主要是关于线条的样式设置 lineWidth: 设置线条的宽 ...

  9. ps添加的阴影怎么去除_【PS摄影后期教程】去除阴影色块三种方法

    点击蓝字关注这个神奇的公众号- 如何去除面部阴影色块 后期时模特面部有不均匀阴影色块 相信这个问题小伙伴们肯定都遇到过 不管是光的原因还是技术的问题 都是无可避免的 阴影有时候能帮助你调整视觉重心 或 ...

  10. python批量读取csv文件-使用Python读写csv文件的三种方法

    行之间无空行十分重要,如果有空行或者数据集中行末有空格,读取数据时一般会出错,引发[list index out of range]错误.PS:已经被这个错误坑过很多次! 使用python I/O写入 ...

最新文章

  1. 往邮箱里发python怎么发_Python 超简单的邮件发送方法
  2. 微信小程序下拉刷新/上拉加载更多
  3. hdu 1874(Dijkstra + Floyd)
  4. 【AI视野·今日CV 计算机视觉论文速览 第204期】Mon, 24 May 2021
  5. 读书笔记_打开量化投资的黑箱07
  6. 零基础入门语义分割-Task5 模型训练与验证
  7. java虚拟机深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)
  8. TypeError: cannot unpack non-iterable int object查找指定文件夹下指定文件类型的数量
  9. 【图像几何】基于matlab GUI图像空间变换(仿射变换)【含Matlab源码 841期】
  10. 跟阿铭学linux书摘
  11. 2020牛客多校训练2 I Interval(对偶图最短路求最小割)
  12. 一网打尽Mac上的高效工具 - 系统工具篇(附演示视频)
  13. 360优化开机速度后慢了_电脑开机速度慢的原因及解决方法
  14. 一文详解:中信银行java笔试题库
  15. 发现一个识图比较厉害的网站
  16. centos主机测磁盘读写速度极限
  17. RSA no_padding加密(modulus、exponent构造公钥)
  18. 鼠标点击添加动态类名active
  19. 用matlab求互谱cpsd,互相关函数Rxy(C)
  20. Android手机多媒体

热门文章

  1. java nio 断开连接_JAVA NIO写服务端判断客户端断开连接的方法
  2. c语言scanf用法
  3. c语言中scanf的用法
  4. linux ftp lcd 命令,Linux FTP命令使用实例
  5. structure 2.3.4 软件使用指南
  6. 软件用户手册编写指南(GB8567一88/GB8567一2006)
  7. oracle gis费用,MapGIS 10 for Desktop 标准版_Oracle
  8. 振动信号的短时傅里叶变换分析
  9. 飞鸽传书2007绿色版下载
  10. 关于vivo手机调试安装“解析程序包时出现问题”的解决方案