时至今日,Webpack 已经成为前端工程必备的基础工具之一,不仅被广泛用于前端工程发布前的打包,还在开发中担当本地前端资源服务器(assets server)、模块热更新(hot module replacement)、API Proxy 等角色,结合 ESLint 等代码检查工具,还可以实现在对源代码的严格校验检查。

正如上文中提到的,前端从开发到部署前都离不开 Webpack 的参与,而 Webpack 的默认配置文件只有一个,即 webpack.config.js,那么问题来了,开发期和部署前应该使用同一份 Webpack 配置吗?答案肯定是否定的,既然 webpack.config.js 是一个 JS 文件,我们当然可以在文件里写 JavaScript 业务逻辑,通过读取环境变量 NODE_ENV 来判断当前是在开发(dev)时还是最终的生产环境(production),然而很多同学习惯把这两者的配置都混写在根目录下的 webpack.config.js,通过很多零散的 if…else 来“临时”决定某一个 plugin 或者某一个 loader 的配置项,随着 loaders 和 plugins 的不断增加,久而久之 webpack.config.js 变得原来越隆长,代码的可读性和可维护性也大大下降。

我想通过本文来介绍一种用 3 个 JS 文件来配置 Webpack 的方法,这里借鉴了很多开源项目的配置,同时也结合了我们自己在开发中碰到的种种问题解决方案。

本文中提及的配置基于 Webpack 2 或以上,建议使用 3.0 及以上版本

开发环境与生产环境的区别

  • 开发环境

    NODE_ENV 为 development

    启用模块热更新(hot module replacement)

    额外的 webpack-dev-server 配置项,API Proxy 配置项

    输出 Sourcemap

  • 生产环境

    NODE_ENV 为 production

    将 React、jQuery 等常用库设置为 external,直接采用 CDN 线上的版本

    样式源文件(如 css、less、scss 等)需要通过 ExtractTextPlugin 独立抽取成 css 文件

    启用 post-css

    启用 optimize-minimize(如 uglify 等)

    中大型的商业网站生产环境下,是绝对不能有 console.log() 的,所以要为 babel 配置 Remove console transform

    这里需要说明的是因为开发环境下启用了 hot module replacement,为了让样式源文件的修改也同样能被热替换,不能使用 ExtractTextPlugin,而转为随 JS Bundle 一起输出。

你需要三份配置文件

  1. webpack.base.config.js
    在 base 文件里,你需要将开发环境和生产环境中通用的配置集中放在这里:

    const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');
const webpack = require('webpack'); // 配置常量
// 源代码的根目录(本地物理文件路径)
const SRC_PATH = path.resolve('./src');
// 打包后的资源根目录(本地物理文件路径)
const ASSETS_BUILD_PATH = path.resolve('./build');
// 资源根目录(可以是 CDN 上的绝对路径,或相对路径)
const ASSETS_PUBLIC_PATH = '/assets/'; module.exports = {
context: SRC_PATH, // 设置源代码的默认根路径
resolve: {
extensions: ['.js', '.jsx'] // 同时支持 js 和 jsx
},
entry: {
// 注意 entry 中的路径都是相对于 SRC_PATH 的路径
vendor: './vendor',
a: ['./entry-a'],
b: ['./entry-b'],
c: ['./entry-c']
},
output: {
path: ASSETS_BUILD_PATH,
publicPath: ASSETS_PUBLIC_PATH,
filename: './[name].js'
},
module: {
rules: [
{
enforce: 'pre', // ESLint 优先级高于其他 JS 相关的 loader
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'eslint-loader'
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
// 建议把 babel 的运行时配置放在 .babelrc 里,从而与 eslint-loader 等共享配置
loader: 'babel-loader'
},
{
test: /\.(png|jpg|gif)$/,
use:
[
{
loader: 'url-loader',
options:
{
limit: 8192,
name: 'images/[name].[ext]'
}
}
]
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use:
[
{
loader: 'url-loader',
options:
{
limit: 8192,
mimetype: 'application/font-woff',
name: 'fonts/[name].[ext]'
}
}
]
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use:
[
{
loader: 'file-loader',
options:
{
limit: 8192,
mimetype: 'application/font-woff',
name: 'fonts/[name].[ext]'
}
}
]
}
]
},
plugins: [
// 每次打包前,先清空原来目录中的内容
new CleanWebpackPlugin([ASSETS_BUILD_PATH], { verbose: false }),
// 启用 CommonChunkPlugin
new webpack.optimize.CommonsChunkPlugin({
names: 'vendor',
minChunks: Infinity
})
]
};
  1. webpack.dev.config.js

这是用于开发环境的 Webpack 配置,继承自 base: const webpack = require('webpack'); // 读取同一目录下的 base config
const config = require('./webpack.base.config'); // 添加 webpack-dev-server 相关的配置项
config.devServer = {
contentBase: './',
hot: true,
publicPath: '/assets/'
};
// 有关 Webpack 的 API 本地代理,另请参考 https://webpack.github.io/docs/webpack-dev-server.html#proxy config.module.rules.push(
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
],
exclude: /node_modules/
}
); // 真实场景中,React、jQuery 等优先走全站的 CDN,所以要放在 externals 中
config.externals = {
react: 'React',
'react-dom': 'ReactDOM'
}; // 添加 Sourcemap 支持
config.plugins.push(
new webpack.SourceMapDevToolPlugin({
filename: '[file].map',
exclude: ['vendor.js'] // vendor 通常不需要 sourcemap
})
); // Hot module replacement
Object.keys(config.entry).forEach((key) => {
// 这里有一个私有的约定,如果 entry 是一个数组,则证明它需要被 hot module replace
if (Array.isArray(config.entry[key])) {
config.entry[key].unshift(
'webpack-dev-server/client?http://0.0.0.0:8080',
'webpack/hot/only-dev-server'
);
}
});
config.plugins.push(
new webpack.HotModuleReplacementPlugin()
); module.exports = config;
  1. webpack.config.js

这是用于生产环境的 webpack 配置,同样继承自 base: const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin'); // 读取同一目录下的 base config
const config = require('./webpack.base.config'); config.module.rules.push(
{
test: /\.less$/,
use: ExtractTextPlugin.extract(
{
use: [
'css-loader',
'less-loader'
],
fallback: 'style-loader'
}
),
exclude: /node_modules/
}
); config.plugins.push(
// 官方文档推荐使用下面的插件确保 NODE_ENV
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
}),
// 启动 minify
new webpack.LoaderOptionsPlugin({ minimize: true }),
// 抽取 CSS 文件
new ExtractTextPlugin({
filename: '[name].css',
allChunks: true,
ignoreOrder: true
})
); module.exports = config;

现在在你的工程文件夹里应该已经有三个 Webpack 配置文件,它们分别是:

webpack.base.config.js

webpack.dev.config.js

webpack.config.js

最后,你还需要在 package.json 里添加相应的配置:


{
...
"scripts": {
"build": "webpack --optimize-minimize",
"dev": "webpack-dev-server --config webpack.dev.config.js",
"start": "npm run dev" // 或添加你自己的 start 逻辑
},
...
}

和很多项目一样,在开发环境下的时候,你需要使用 npm run dev 来启动,而在生产环境中,则用 npm run build 来发布。

为什么我们要做三份 Webpack 配置文件的更多相关文章

  1. webpack 配置文件相关解说

    博客地址:https://ainyi.com/10 webpack - 什么是webpack: WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它 ...

  2. webpack实践(二)- webpack配置文件

    webpack系列博客中代码均在github上:https://github.com/JEmbrace/webpack-practice <webpack实践(一)- 先入个门> < ...

  3. webpack基础+webpack配置文件常用配置项介绍+webpack-dev-server

    一.webpack基础 1.在项目中生成package.json:在项目根目录中输入npm init,根据提示输入相应信息.(也可以不生成package.json文件,但是package.json是很 ...

  4. 调试webpack配置文件

    webpack运行在nodejs上,调试webpack就相当于调试nodejs程序.下面介绍一种通用的办法. 1.配置package.json,加一个debug. { 'scripts': { 'de ...

  5. react暴露webpack配置文件

    在react中安装create-react-app脚手架新建项目,但是新建的项目中没有配置文件. webpack的配置文件webpack.base.conf.js隐藏在了node_modules文件夹 ...

  6. 3.WebPack配置文件

    一.为什么需要WebPack配置文件 引用自官方: 在 webpack 4 中,可以无须任何配置使用,然而大多数项目会需要很复杂的设置,这就是为什么 webpack 仍然要支持 配置文件.这比在终端( ...

  7. 3.使用webpack配置文件webpack.confg.js配置打包文件的入口和出口

    在项目根目录下新建webpack.config.js文件 webpack.config.js文件配置如下: // Node的路径操作使用的是path模块 const path=require('pat ...

  8. webpack 配置文件

    现如今,webpack非常的受欢迎,比较火的几款js框架都推荐使用webpack来构建项目,而webpack也确实非常强大,但是配置webpack缺常常带来很多问题,接下来就写一下我自己遇到的一些坑. ...

  9. nginux做反向代理配置文件

    做反向代理的配置文件最好单独创建一个文件,然后在主配置文件中使用 include nginx-test.config;  这样的方式来导入. 配置代码如下: ## Basic reverse prox ...

随机推荐

  1. css,js移动资源

    随着移动市场的逐步扩大及相关技术的日趋完善,对前端开发提出了新的岗位要求,在继承前人成果的基础上需要在新的历史条件下有新的创新.移动端的开发,虽然没有IE6众多问题的折磨,但是多平台,多设备的兼容,也 ...

  2. Ubuntu16.04 安装maven

    maven是个项目管理工具,在编程领域应用广泛.本文主要讲述如何在ubuntu16.04系统下安装maven. 第一步,去官网下载maven. 第二步,解压到/opt/maven目录. 创建manve ...

  3. Java EE大作业之创造class类出现问题-------Implicit super constructor Object() is undefined for default constructor. Mu

    这个学期一直在忙着考驾照的事情,眼看就要期末了.我的大学生活的最后一个大的作业也要来临了.说实话这个学期真的是没有之前的两个学期努力了.不知道是快要毕业的缘故还是真的是把心思用在了驾照上,想着在这次放 ...

  4. 使用postMessage通信,未触发message事件

    前提: 父子页面跨域通信,使用postMessage技术 a页面为父页面,b页面为子页面 a中包含多个iframe,部分域名是相同的,目录层级不一致,地址使用变量根据触发的条件不同拼接地址 部分代码( ...

  5. JQuery 更改属性 JQ对象循环 each 全选反选 三元运算

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. java多线程中的死锁、活锁、饥饿、无锁都是什么鬼?

    死锁.活锁.饥饿是关于多线程是否活跃出现的运行阻塞障碍问题,如果线程出现了这三种情况,即线程不再活跃,不能再正常地执行下去了. 死锁 死锁是多线程中最差的一种情况,多个线程相互占用对方的资源的锁,而又 ...

  7. CAD增强属性块的还原(转)

    来自:http://blog.3snews.net/space.php?uid=13924959&do=blog&id=70174 作者:毛毛虫 Demo下载:CAD增强属性块的还原 ...

  8. Python 爬虫 获取标签下面的子标签

    thr_msgs = soup.find_all('div',class_=re.compile('msg')) for i in thr_msgs: print(i) first = i.selec ...

  9. Oracle SQL语句操作数字:取整、四舍五入及格式化

    用oracle sql对数字进行操作: 取上取整.向下取整.保留N位小数.四舍五入.数字格式化 取整(向下取整): select floor(5.534) from dual;select trunc ...

  10. ZT fcntl设置FD_CLOEXEC标志作用

    fcntl设置FD_CLOEXEC标志作用 分类: C/C++ linux 2011-11-02 22:11 3217人阅读 评论(0) 收藏 举报 bufferexegccnullfile 通过fc ...