创建 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 (
<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 {
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模式
参考
react-code-previewer
hiynn-design
JavaScript模块化CommonJS/AMD/CMD/UMD/ES6Module的区别
前端构建工具发展及其比较
cuke-ui
ant-landing)
黄瓜 UI: 一个即插即用的 React 组件库
webpack4 SplitChunks实现代码分隔详解
Show me the code,babel 7 最佳实践!
使用模块化工具打包自己开发的JS库(webpack/rollup)对比总结
gulp实战(2) - 自动化打包CSS文件(完整版)
打包平台Webpack(V3-V4)和Babel(V6-V7)升级~
[babel.config.js、.babelrc、.babelrc.js 区别
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。