全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

为什么我们要做三份 Webpack 配置文件

在知乎上我们常常会看到有同学发问:BAT 等大型网站的前端工程是如何组织管理的?这的确是一个可以发散的很广的 Q&A,我想如果要我回答这个问题,不如先从 Webpack 配置说起。

时至今日,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
  })
 ]
};

2. webpack.dev.config.js

这是用于开发环境的 Webpack 配置,继承自 base:

const webpack = require('webpack');

// 读取同一目录下的 base config
const config = require('./webpack.base.config');

// 添加 webpack-dev-server 相关的配置项
config.devServer = {
 contentBase: './',
 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;

3. 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-dev-server,而采用 express + webpack/webpack-dev-middleware,配置方法与上面所述的完全相同。

关于专栏

如果你喜欢这篇文章,就请关注我的专栏《前端零栈》,在这里我们一起聊一聊前端技术和前端工程。

关于作者

Henry,10 岁开始学习计算机编程,高二暑假获得江苏省青少年信息奥林匹克一等奖。2000 年开始自学 JavaScript 及网页制作,2006 年起正式开始从事前端开发工作,从此一干就是 10 多年。加入阿里巴巴前,曾在 SAP 中国研究院担任智慧交通大数据产品经理。

Github:MagicCube (Henry Li)

 小结

前端从开发到部署前都离不开 Webpack 的参与,本文结合了我们自己在开发中碰到的种种问题解决方案,同时借鉴了很多开源项目的配置来介绍一种用 3 个 JS 文件来配置 Webpack 的方法。关于本文如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


# javascript  # webpack  # 配置文件  # 一次Webpack配置文件的分离实战记录  # 详解webpack的配置文件entry与output  # webpack教程之webpack.config.js配置文件  # 详解vue2.0脚手架的webpack 配置文件分析  # webpack配置文件和常用配置项介绍  # vue-cli的webpack模板项目配置文件分析  # webpack常用配置项配置文件介绍  # webpack配置文件外置的两种实现方式  # 是一个  # 放在  # 这是  # 我想  # 源代码  # 开源  # 自己的  # 的是  # 都是  # 奥林匹克  # 是在  # 来了  # 在这里  # 景中  # 目录下  # 还可以  # 还在  # 在此  # 不需要 


相关文章: 建站之星安装提示数据库无法连接如何解决?  建站之星如何一键生成手机站?  天津个人网站制作公司,天津网约车驾驶员从业资格证官网?  制作门户网站的参考文献在哪,小说网站怎么建立?  c++ stringstream用法详解_c++字符串与数字转换利器  如何用花生壳三步快速搭建专属网站?  魔毅自助建站系统:模板定制与SEO优化一键生成指南  网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?  北京网页设计制作网站有哪些,继续教育自动播放怎么设置?  如何高效完成自助建站业务培训?  上海网站制作网页,上海本地的生活网站有哪些?最好包括生活的各个方面的?  如何快速启动建站代理加盟业务?  黑客如何利用漏洞与弱口令入侵网站服务器?  制作网站外包平台,自动化接单网站有哪些?  股票网站制作软件,网上股票怎么开户?  定制建站平台哪家好?企业官网搭建与快速建站方案推荐  如何快速搭建虚拟主机网站?新手必看指南  C++如何使用std::optional?(处理可选值)  深入理解Android中的xmlns:tools属性  浙江网站制作公司有哪些,浙江栢塑信息技术有限公司定制网站做的怎么样?  建站中国必看指南:CMS建站系统+手机网站搭建核心技巧解析  免费网站制作模板下载,除了易企秀之外还有什么H5平台可以制作H5长页面,最好是免费的?  如何规划企业建站流程的关键步骤?  高性能网站服务器配置指南:安全稳定与高效建站核心方案  香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧  宝塔建站教程:一键部署配置流程与SEO优化实战指南  c# 在ASP.NET Core中管理和取消后台任务  建站之星安装路径如何正确选择及配置?  网站制作中优化长尾关键字挖掘的技巧,建一个视频网站需要多少钱?  建站之星伪静态规则如何正确配置?  建站一年半SEO优化实战指南:核心词挖掘与长尾流量提升策略  济南网站建设制作公司,室内设计网站一般都有哪些功能?  如何在宝塔面板创建新站点?  桂林网站制作公司有哪些,桂林马拉松怎么报名?  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?  建站之星后台管理如何实现高效配置?  建站之星图片链接生成指南:自助建站与智能设计教程  网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?  如何在IIS中新建站点并解决端口绑定冲突?  金*站制作公司有哪些,金华教育集团官网?  如何在香港免费服务器上快速搭建网站?  建站之星代理如何优化在线客服效率?  网站制作多少钱一个,建一个论坛网站大约需要多少钱?  如何通过主机屋免费建站教程十分钟搭建网站?  如何获取上海专业网站定制建站电话?  如何用免费手机建站系统零基础打造专业网站?  制作网站的软件下载免费,今日头条开宝箱老是需要下载怎么回事?  如何在局域网内绑定自建网站域名?  专业的网站制作设计是什么,如何制作一个企业网站,建设网站的基本步骤有哪些? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。