为什么我们要做三份 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 相关的 loadertest: /\.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 }),// 启用 CommonChunkPluginnew webpack.optimize.CommonsChunkPlugin({names: 'vendor',minChunks: Infinity})]};
  1. webpack.dev.config.js
这是用于开发环境的 Webpack 配置,继承自 base:const webpack = require('webpack');// 读取同一目录下的 base configconst 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#proxyconfig.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 replacementObject.keys(config.entry).forEach((key) => {// 这里有一个私有的约定,如果 entry 是一个数组,则证明它需要被 hot module replaceif (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 configconst 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_ENVnew webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')}),// 启动 minifynew 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 来发布。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370130.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用maven插件构建docker镜像

为什么要用插件 主要还是自动化的考虑,如果额外使用Dockerfile进行镜像生成,可能会需要自己手动指定jar/war位置,并且打包和生成镜像间不同步,带来很多琐碎的工作。 插件选择 使用比较多的是spotify的插件:https://github.com/spo…

windows下如何安装pip以及如何查看pip是否已经安装成功?

最近刚学习python,发现很多关于安装以及查看pip是否安装成的例子都比较老,不太适合于现在(python 3.6 )因此,下一个入门级别的教程。 0:首先如何安装python我就不做介绍了。 1:如果安装的是pyth…

检查用户显示器的分辨率

检查用户显示器的分辨率 转载于:https://www.cnblogs.com/Renyi-Fan/p/8088012.html

android 字体 dpi,详解Android开发中常用的 DPI / DP / SP

Android的碎片化已经被喷了好多年,随着国内手机厂商的崛起,碎片化也越来越严重,根据OpenSignal的最新调查,2014年市面上有18796种不同的Android设备,作为开发者,一个无法回避的难题就是需要适配各种各样奇奇…

android studio闪退代码不报错_代码不报错,不代表真的没错

今天是生信星球陪你的第695天大神一句话,菜鸟跑半年。我不是大神,但我可以缩短你走弯路的半年~就像歌儿唱的那样,如果你不知道该往哪儿走,就留在这学点生信好不好~这里有豆豆和花花的学习历程,从新手到进阶&#xff0c…

Centos7操作系统部署指南

一、硬件环境: Dell R620 二、软件环境: Centos6.4 X86_64 KVM Windows7vnc 三、安装说明 操作系统更新之迅速,让作为新手的系统运维人员有点措手不及,相对于老手就胸有成竹。怎么讲?由于老手对技术方向把握的非常好&…

Eclipse插件中的SLF4J登录

一直都在使用Maven和纯Java库进行开发,我从没想过在开发Eclipse插件时发出一些日志语句可能会成为问题。 但是,在Eclipse开发人员的想象中,一切似乎总是在Eclipse环境中,而Eclipse宇宙之外则什么都没有。 如果您使用Google搜索上…

CSS(四)

css元素溢出 当子元素的尺寸超过父元素的尺寸时,需要设置父元素显示溢出的子元素的方式,设置的方法是通过overflow属性来设置。 overflow的设置项: 1、visible 默认值。内容不会被修剪,会呈现在元素框之外。2、hidden 内容会被修…

mysql排名

转载自思心思危http://www.cnblogs.com/zengguowang/p/5541431.html 一、sql1{不管数据相同与否,排名依次排序(1,2,3,4,5,6,7.....)} SELECTobj.user_id,   obj.score,  rownum : rownum 1 AS rownum FROM(SELECT…

python中变量名后的逗号_深入浅析python变量加逗号,的含义

逗号,用于生成一个长度为1的元组>>> (1)1>>> (1,)(1,)>>> 1,(1,)因此需要将长度为1的元组中元素提取出来可以用,简化赋值操作>>> a(1,)>>> ba>>> b(1,)>>> b,a>>> b1最后print打印变量加,实现连续打印…

广告的显示和关闭

app或游戏的主页显示广告页面,实现方式: public class MainActivity extends Activity implements View.OnClickListener{private Button btnShowAd;private RelativeLayout layoutAd;Overrideprotected void onCreate(Bundle savedInstanceState) {supe…

android签到功能模块,基于android的课堂签到系统.doc

基于android的课堂签到系统本科毕业论文(设计)题 目 基于Android的课堂签到系统学生姓名 XXX指导教师 XX学 院 信息科学与工程学院专业班级 计算机科学与技术0908班完成时间 2013年5月 摘 要在大学课堂中,签到问题一直困扰着老师和同学们。传统课堂签到的手段大多是…

Java EE 7社区调查结果!

在JSR 342下可以继续进行Java EE 7的工作。一切进展顺利,Java EE 7现在处于“初稿审查”阶段。 在11月初, Oracle发布了一个有关即将推出的Java EE 7功能的小型社区调查 。 昨天结果公布了。 超过1,100名开发人员参加了调查,并且几乎对每个问…

CSS(三)

CSS盒子模型 盒子模型解释 元素在页面中显示成一个方块,类似一个盒子,CSS盒子模型就是使用现实中盒子来做比喻,帮助我们设置元素对应的样式。盒子模型示意图如下: 把元素叫做盒子,设置对应的样式分别为:盒…

一道关于运行顺序题

function foo(){   getName function(){console.log(1)}   return this } foo.getName function(){console.log(2)} foo.prototype.getName function(){console.log(3)} var getName function(){console.log(4)} function getName(){console.log(5)} foo.getName()//2 …

android+小米文件管理器源码,小米开源文件管理器MiCodeFileExplorer-源码研究(2)-2个单实例工具类...

从本篇开始,讲解net.micode.fileexplorer.util工具包中的类。这个包下的类,功能也比较单一和独立。很多代码的思想和实现,可以用于JavaWeb和Android等多种环境中。一、单实例活动管理器ActivitiesManager一个单实例的活动管理器,从…

移动优先的响应式布局

前面的话 随着移动互联网的兴起,不同设备的分辨率相差较大,如果在不同的设置上显示同一个页面,则用户体验差。响应式网页设计是一种方法,使得一个网站能够兼容多个终端,而不用为每个终端制作特定的版本。它使得一个网站…

python中英文字符和中文字符存储长度不同_Django如何正确截取中英混合字符串及表单中限制中文字符中长度...

中文字符和英文字符所占的字节长度是不一样,一个是2个字节,一个是1个字节,这给我们用英文的web框架开发中文app带来了麻烦。比如Django自带过滤器truncatewords并不支持截取中文,另外模型中CharField中的max_length选项用于限制中…

使用RESTful客户端API进行GET / POST

互联网上有很多如何使用RESTful Client API的东西。 这些是基础。 但是,尽管该主题看起来微不足道,但仍然存在一些障碍,尤其是对于初学者而言。 在这篇文章中,我将尝试总结我的专业知识,以及我如何在实际项目中做到这…

南昌互联网行业协会筹办者祝真和华罡团队-2014年12月江西IDC排行榜

他出自军营,拥有一身正气。 他在南昌创业,立意卓越。 从站点開始、到微营销、到线上教育,全面开花。 他在朋友圈看到不对的内容,就会即时批评。 他对朋友,又是很的和蔼可亲。 他就是南昌华罡网…