webpack 启动器,简化 webpack 繁杂配置,提供便捷的使用方式。
目前此工具只在 mac 平台进行测试,后续会针对 windows 进行测试。
npm i webpack-launcher -D
安装完毕后运行运行一下命令,即可运行样板代码。
npm run init-webpack-launcher
npm start
注意:
npm run init-webpack-launcher
(postinstall 会添加添加此命令,直接使用即可)。此命令的内容为:webpack-launcher init
,运行此命令后可在终端看到如下信息:
Adding ./public folder.
Adding ./src folder.
Deleting npm run init-webpack-launcher
Adding npm run eject as webpack-launcher eject
Adding npm run start as webpack-launcher start
Adding npm run build as webpack-launcher build
Adding npm run serve-build as webpack-launcher serve-build
如果 public 文件夹存在,程序会直接中断。
如果 src 文件夹存在,直接使用已存在的 src 文件夹并警告:
Adding ./public folder.
The src folder is exited, use the exited src folder instead.
Please make sure the entry file ./src/index.js is exited.
Deleting npm run init-webpack-launcher
Rewriting npm run eject as webpack-launcher eject
Rewriting npm run start as webpack-launcher start
Rewriting npm run build as webpack-launcher build
Rewriting npm run serve-build as webpack-launcher serve-build
首先安装 @babel/[email protected]
这里需要在项目根目录添加 .babelrc.js
:
'use strict';
module.exports = {
presets: [
// 支持 react jsx
['@babel/react'],
],
};
然后在 src/index.js 入口文件添加 React 代码即可,其他无改动。
安装 npm i less less-loader
,安装完后 npm start
启动即可,无需做任何其他配置。
安装 npm i node-sass sass-loader
,安装完后 npm start
启动即可,无需做任何其他配置。
注意:安装 node-sass 可能会出现各种错误,或者安装不了,即使你切换到淘宝镜像,也解决不了这种问题。本人通过在 ~/.npmrc
添加如下代码,然后安装没出现什么问题,安装也挺快(ps:不过我已经不用 Sass,不知道现在什么情况)。
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
webpack-launcher 配置文件命名为 .webpack.launcher.js
,直接在项目根目录新建文件即可,默认的配置为:
// 这里可配置一些常用的配置,如果满足不了,需要 eject
// 相对路径为,npm 项目根目录
module.exports = {
// 因为有些网站访问web app不是在根目录,可能是根目录中的的文件夹,basename是用来设置这种情况的
// 例如`/demo`,访问网站根目录demo文件中的web app
servedPath: '/',
appSrc: './src',
appIndexJs: './src/index.js',
appBuild: './build',
appPublic: './public',
appHtml: './public/index.html',
// https://webpack.docschina.org/configuration/dev-server/#devserver-host
host: 'localhost',
// https://webpack.docschina.org/configuration/dev-server/#devserver-port
port: 8888,
// https://webpack.docschina.org/configuration/dev-server/#devserver-proxy
// proxy 优先级高于 mock
proxy: {},
// 默认使用使用 mock 服务
// 不需要可以关闭 mock 服务
useMockServer: true,
// 是否开启 https
https: false,
// 设置 webpack alias
// https://webpack.docschina.org/configuration/resolve/#resolve-alias
alias: {},
// 设置 process.env.NODE_ENV 等全局变量
// 格式 webpack.DefinePlugin 一样。
// https://webpack.docschina.org/plugins/define-plugin/
globals: {},
// 是否开启 sourceMap 包括 less、postcss、js 等 sourceMap,只对生产环境有效
sourceMap: true,
// webpackHotDevClient,有两种选择:
// default: webpack 默认的热替换热替换方式(需要手动开启)
// create-react-app: craate-react-app 热替换方式(默认开启这个)
webpackHotDevClient: 'create-react-app',
// 打包的 js、css 文件会被 gzip(后缀名还是 js 或者 css,但是内容已经 gzip)
// 默认不开启
buildGzip: false,
// 是否压缩,压缩包命名例如 `{name}-frontend-v{version}.tar.gz`
tar: undefined,
// dll 建议配置
dllEntry: undefined,
appDllBuild: './public/dll',
// Automatically split vendor and commons
// https://twitter.com/wSokra/status/969633336732905474
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
// webpack 配置 optimization.splitChunks
// create-react-app 的默认值为:
// {
// chunks: 'all',
// name: false,
// },
splitChunks: undefined,
// Keep the runtime chunk seperated to enable long term caching
// https://twitter.com/wSokra/status/969679223278505985
// webpack 配置 optimization.runtimeChunk
runtimeChunk: false,
};
功能列表会逐一说明,说有配置都是可选的。
-
默认的 babel 配置
-
HTTP API 模拟(mock)
-
反向代理
-
域名 host 绑定
-
Https
-
别名(alias)
-
环境全局变量(如 process.env.NODE_ENV)
-
热替换
-
webpack dll
-
js、css 内容 gzip
-
构建 tar.gz 压缩包
-
构建后的 web 静态服务
'use strict';
const { NODE_ENV } = process.env;
module.exports = {
presets: [
[
'@babel/env',
{
targets: {
browsers: ['ie >= 11'],
},
// 测试环境需要把 import转换成 commonjs require 模式
modules: NODE_ENV === 'test' || NODE_ENV === 'TEST' ? 'commonjs' : false,
// 为了避免一些问题,使用 false
loose: false,
},
],
],
plugins: [
// Currently, @babel/preset-env is unaware that using import()
// with Webpack relies on Promise internally.
// Environments which do not have builtin support for Promise,
// like Internet Explorer, will require both the promise and
// iterator polyfills be added manually.
'@babel/plugin-syntax-dynamic-import',
// 这个是 es7 提案,并不是标准,用法如下
// 这里使用 legacy (stage 1) decorators 语法和行为。
// @decorator
// class Test {}
// 当 legacy = true 时,需要用在 `@babel/plugin-proposal-class-properties`
// 之前,否则无效
['@babel/plugin-proposal-decorators', { legacy: true }],
// 使用 class properties 新用法
// class Test {
// displayName = 'test';
// }
'@babel/plugin-proposal-class-properties',
// 需要配套安装 @babel/runtime(dependencies,非 devDependencies)
// 其中 helper 功能可以减少转换生成的代码(通过引用 @babel/runtime)
'@babel/plugin-transform-runtime',
],
};
这个功能在开发前期比较常用,可以保证和后端的同步开发。webpack-launcher
mock 有以下优点:
-
容易上手
express API 使用方式,如下:
module.exports = function(mockApp) { mockApp.get('/keeper/v1/topic', function(req, res) { res.send({ url: req.url, query: req.query }); }); mockApp.post('/keeper/v1/topic', function(req, res) { res.send({ url: req.url, query: req.query }); }); mockApp.patch('/keeper/v1/topic/:id', function(req, res) { res.send({ url: req.url, query: req.query, body: req.body, 'data|10': [{ 'id|+1': 1 }], }); }); mockApp.delete('/keeper/v1/topic/:id', function(req, res) { res.send({ url: req.url, query: req.query }); }); };
-
动态加载,服务启动后,修改 mock 文件后,无需重启服务,再次访问即可
-
直接支持 mock.js 语法
后续会继承一些更便捷的组合方式提供选用,使用者也可以基于 mock 用法进行开发新用法。
webpack-launcher
一切准备后之后,在项目根目录新建 mock
文件夹,并新建 .mock.config.js
文件。
.mock.config.js
是 mock 程序的唯一入口,结构为:
module.exports = function(mockApp) {
// 可以简单的把 mockApp 当做 express app
};
在 .mock.config.js
中编写好 mock 内容,然后 npm start
启动服务(中途修改 mock 内容无需重启)。
如果你要完全禁止这 mock 可以在 .webpack.launcher.js
进行如下配置:
module.exports = {
useMockServer: false,
};
这个用法跟 webpack-dev-server proxy 配置一样,请参考 webpack 文档。
使用此项功能可以在 .webpack.launcher.js
进行如下配置,默认值为 localhost:
module.exports = {
host: 'webpack.launcher.com',
};
启动服务后,会自动更新 host 到系统 hosts 文件。
是否使用 https 协议启动服务,默认不开启,用法请看 webpack-dev-server 文档,这里.webpack.launcher.js
配置简化为:
module.exports = {
https: true,
};
webpack alias,用法请看 webpack alias 文档,这里 .webpack.launcher.js
配置 简化为:
module.exports = {
alias: {
src: path.resolve('./src'),
// dayjs 可以减少代码量,目前没用到 moment 的地方
// 大部分 api dayjs 都可以替换 moment
// 以后用到需要看看有没有影响
moment: path.resolve('./node_modules/dayjs/dayjs.min.js'),
// 为了减少打包体积,无需引入多余的 icon
'@ant-design/icons/lib/dist$': path.resolve('./src/icons.js'),
},
};
即 webpack DefinePlugin 配置:
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
BROWSER_SUPPORTS_HTML5: true,
TWO: '1+1',
'typeof window': JSON.stringify('object'),
});
这里 .webpack.launcher.js
配置 简化为:
module.exports = {
globals: {
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
BROWSER_SUPPORTS_HTML5: true,
TWO: '1+1',
'typeof window': JSON.stringify('object'),
},
};
这个是新功能,也是 webpack-launcher 的特色,一般开启 gzip 都是在 web 服务器(如 Nginx)处理,web 服务器响应内容给浏览器客户端时会进行内容 gzip 压缩,然后浏览器进行解压后使用。
而使用了此功能,静态文件 js 和 css 文件会被 gzip,无需 web 服务器进行压缩,省略了这一步。如果使用此功能,web 服务器需要做一个特殊处理,响应头需要添加 Content-Encoding: gzip
(Nginx 不能设置为 gzip: true,而是手动添加响应头)。
.webpack.launcher.js
配置如下:
module.exports = {
buildGzip: true,
};
热替换有两种值选择:
-
default
webpack 默认的热替换热替换方式(需要手动开启),如果你想使用
react-hot-loader
你就必须使用此方式。 -
create-react-app
craate-react-app 热替换方式(webpack-launcher 默认开启这个)
如果你使用 webpack 直接配置 dll,那么这将会比较繁杂,但是如果你使用 webpack-launcher
,那边将会非常简单。
.webpack.launcher.js
配置如下:
module.exports = {
dllEntry: {
main: ['react', 'react-dom'],
other: ['redux', 'react-redux'],
},
};
请确保 node_modules 下提取到 dll 的包已存在,如果你使用的是 lerna 之类的多包管理工具(monorepo),不用担心,也没问题。
webpack-launcher dll
支持多个入口,根据实际项目情况划分即可。
这个你完全可以不能担心,只要你运行 npm start
或者 npm run build
,程序会对比当前的 dllEntry 配置,如果发现 dllEntry 结构、package 版本变化(node_modules package 版本)会自动运行 npm run build-dll
命令内容,并生存 dll 文件。dll 生成后的文件位于根目录 ./public/dll
文件夹下。
没错生存的 dll 文件名都附带 8 位 hash 命名,不存在不同版本缓存问题,所以如果你手动运行了 npm run build
,那边你需要重启服务。
.webpack.launcher.js
配置如下:
module.exports = {
tar: `{name}-frontend-v{version}.tar.gz`,
};
其中 {name}
会替换为 package.json 的 name 字段,{version}
会替换为 package.json 的 version
字段。
为了方便验收构建后的 web app,webpack launcher 也提供了静态服务功能,同时 .webpack.launcher.js
的 配置页使用于静态服务(除开 webpack 开发环境相关的配置,如 alias 等)。
npm run build
构建成功后,直接运行 npm run serve-build
即可(proxy 、mock 配置一样可用)。
如果你想要更好的自定义其他 webpack 功能,你需要用到 eject 功能(如果你用过 create-react-app eject 功能更),那么很好理解。
npm run eject
后终端会输出如下信息:
? Are you sure you want to eject? This action is permanent. Yes
Ejecting...
Adding ./.eslintrc.js
Adding ./.babelrc.js
Adding ./config/webpack.config.js
Adding ./config/webpackDevServer.config.js
Adding ./config/webpackLauncher.config.js
Adding ./config/webpack.dll.config.js
Adding ./scripts/start.js
Adding ./scripts/build.js
Adding ./scripts/serveBuild.js
Ejected sucessfully!
然后你就可以为所欲为了。