webpack配置实践
首先我们的需求:
- 打包调试
- 提取公共代码
- 压缩
- 热替换
1.打包调试
第一步,我们在目标文件夹下安装webpack(假设已有package.json)npm i webpack@ -gcnpm i webpack@ --save-dev
(这里推荐大家安装稳定的2.x版本)
项目结构如图:
我们将编写的js代码和样式文件放置在app文件夹内(正常项目开发需要js文件和less文件更规范的组织文件结构,此处仅为演示方便)。
第二步,我们在目标文件夹下新建webpack.config.js
module.exports = {
entry:{
main:__dirname + '/app/main.js',
},
output:{
path:__dirname + '/public',
filename:'[name].[id].js',//此格式写法后续会提到为什么
publicPath:'/public/'
}
}
我们已经完成了webpack最基础的部分:添加了文件的输入和输出。入口是app文件夹内的main.js文件,出口为public文件夹。接下来我们来处理各种文件的解析,就是大名鼎鼎的loader的舞台了。假设我们使用es6和less开发,那么我们需要:npm i babel-loader babel-core babel-preset-es2015 babel-preset-stage-0 --save-dev
npm i less less-loader css-loader style-loader --save-dev
接下来我们只需要在modules字段下把这些loader加进去:
module.exports = {
devtool:'cheap-module-eval-source-map',//多种选择,选择最适合自己的
entry:{
main:__dirname + '/app/main.js',
},
output:{
path:__dirname + '/public',
filename:'[name].[id].js',
publicPath:'/public/'
},
module:{
loaders:[
{
test:/\.js$/, //解析文件类型
exclude:/node_modules/, //排除node_modules文件
loader:'babel-loader', //使用哪种loader解析
query:{
presets:['es2015','stage-0']//loader的配置项,解析es6
}
},
{
test:/\.less$/,
exclude:/node_modules/,
loader:'style-loader!css-loader!less-loader'//顺序为从右向左
}
]
},
}
大功告成!
如果你在全局安装有webpack的话,可以在终端敲入webpack并回车,几秒钟后,main.js文件已经在public打包出来了!
之后我们在index.html中引入main.0.js文件,再打开index.html就可以看到效果了。
以上步骤,我们已经实现了文件的打包调试,但是现在有个问题摆在我们面前:第三方库代码和业务代码打包到了同一个文件main.0.js内,每次更新代码都要更新整个文件。那么接下来我们对代码进行拆分。
2.提取公共代码
引入CommonsChunkPlugin插件,在webpack.config.js添加如下内容:
module.exports = {
devtool:'cheap-module-eval-source-map',
entry:{
main:__dirname + '/app/main.js',
vendor:'moment'
},
output:{
path:__dirname + '/public',
filename:'[name].[id].js',
publicPath:'/public/'
},
module:{
loaders:[
{
test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader',
query:{
presets:['es2015','stage-0']
}
},
{
test:/\.less$/,
exclude:/node_modules/,
loader:'style-loader!css-loader!less-loader'
}
]
},
plugins:[
new webpack.optimize.CommonsChunkPlugin({
names:['vendor','manifest']
})
]
}
我们看到向插件的构造函数传入了两个参数vendor和manifest,以及我们在entry也加入了新的入口moment。moment是常用的时间处理的第三方库,我们可以通过npm i moment --save-dev进行安装。而entry处的vendor将成为output字段filename中[name]的值,也就是说将打包出main.x.js和vendor.x.js两个文件,main.x.js文件将保存我们的业务代码,vendor.x.js将保存moment的代码,这样我们将公共代码和业务代码进行了初步分离。
在新添加的CommonmChunkPlugin插件中,我们添加了manifest值,这是为什么呢?如果你不添加这个值,你在打包时会发现,main.x.js有更新,vendor.x.js还是有更新,并未真正实现"分离"。官方文档对此的解释是:
The issue here is that on every build, webpack generates some webpack runtime code, which helps webpack do it’s job. When there is a single bundle, the runtime code resides in it. But when multiple bundles are generated, the runtime code is extracted into the common module, here the vendor file.
大致的意思就是说,webpack每次编译时运行的代码会影响到hash值的变化,当只有一个打包文件时这部分代码会塞进去,当有多个打包文件时,这部分代码会进入公共的vendor。所以解决办法是使用manifest字段把这部分代码从vendor中作为一个公共模块抽出来,从而不会影响vendor。
将以上的配置写入webpack.config.js,运行webpack命令,我们发现业务代码和公共库代码成功分离,改写main.1.js文件的内容,再次打包,发现vendor文件并没有变化,成功!
当我们再进行打包时,发现又会多出了新的main.x.js等文件,打包三次就会出现三个main.x.js文件,此时该怎么办呢?我们可以使用clean-webpack-plugin插件:
npm i clean-webpack-plugin --save-dev
然后在webpack.config.js中引入:
var CleanWebpackPlugin = require('clean-webpack-plugin');
new CleanWebpackPlugin(
['public/main.*.js','public/manifest.*.js'],//要删除的文件目录匹配
{
root:__dirname,
verbose:true,
dry:false
}
),
这样我们每次在打包新的代码时,旧文件就会删除,不会再出现同一份文件存在多份的情况。
3.压缩
在webpack中,图片,css,js等等其他资源皆可压缩,本文仅以压缩js为例。
安装插件:npm i uglifyjs-webpack-plugin --save-dev
在webpack.config.js中引入:
var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
new UglifyJsPlugin({
beautify:true,
exclude:['/node_modules/'],
compress:{
warnings:false
},
output:{
comments:false
}
})
我们指定了压缩的方法,排除了不需要压缩的node_modules部分,同时我们去除了comments部分(comments为@license等注释,是可观的压缩空间)。再次在终端输入打包命令,可见js打包后的体积有令人满意的减小。
4.热替换
webpack总是绕不开热替换的话题。热替换的功能配置和原理是一大话题,三天三夜也说不完,也并非本文重点,本文只提供简易高效的配置方法。
热替换存在两种使用方式,cli和node。cli方式无需添加新的热替换插件,且无需在入口处添加webpack-dev-server等入口,故本文采用cli使用方式。
在webpack.config.js中添加devServer字段,加入如下代码:
devServer:{
inline:true,
hot:true
},
保存后运行webpack-dev-server --inline --hot --progress,再修改下main.less文件的样式,会发现浏览器并没有刷新,但页面已经发生了变化,我们的热替换功能也成功加入了!
tips:
在实际项目打包时,可以将filename字段的值换为[name].[chunkhash].js,其中[chunkhash]为webpack每次打包后给每个模块的标识值,这个值每次打包后都会更换。为什么在此处我们使用[id]呢,因为chunkhash与热替换存在冲突,终端会有报错,那么使用id可以算作一个解决方案。这就引申出另一话题,我们可以使用两套webpack配置分别用于生产环境和开发环境,通过webpack指定config来进行打包。例如我们在开发环境使用id,在生产环境去掉热替换并使用hash的方式。而且,一些压缩插件也没必要在开发环境过度使用,两套配置能让webpack发挥最大的威力。
另外,chunkhash和hash有区别,chunkhash顾名思义是模块的标识,而hash是webpack每次编译的标识值,不同的资源如js和css存在chunkhash解耦的问题,此处不进行过多讨论。
关于热替换的更多细节和原理,参考文章:http://www.cnblogs.com/wonyun/p/7077296.html
5.运行
我们知道,每次打包后,都会有新的main.x.js文件生成,其hash值每次打包后都会发生变化,难道我们的index.html文件需要每次打包后都手动修改main.x.js的路径吗?还好社区提供了html-webpack-plugin插件,可以在已有html模板的条件下自动为我们生成带有最新代码的html文件:
npm i html-webpack-plugin --save-dev
在webpack.config.js中引入:
var HtmlWebpackPlugin = require('html-webpack-plugin');
new HtmlWebpackPlugin({
title:'demo',
template:'index.html'
}),
在终端运行打包命令,我们看到public文件夹下生成了新的index.html文件:
以后我们再进行调试时,以本文为例,则需要打开localhost:8080/public/index.html,因为每次webpack的HtmlWebpackPlugin都会把新的js文件加入到这个html文件内。在开发全部完成后,我们可以将js路径写死,添加到原有的index.html文件中。
以下是我们webpack.config.js全部的配置;
var webpack = require('webpack');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
devtool:'cheap-module-eval-source-map',
entry:{
main:__dirname + '/app/main.js',
vendor:'moment'
},
output:{
path:__dirname + '/public',
filename:'[name].[id].js',
publicPath:'/public/'
},
devServer:{
inline:true,
hot:true
},
module:{
loaders:[
{
test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader',
query:{
presets:['es2015','stage-0']
}
},
{
test:/\.less$/,
exclude:/node_modules/,
loader:'style-loader!css-loader!less-loader'
}
]
},
plugins:[
new CleanWebpackPlugin(
['public/main.*.js','public/manifest.*.js'],
{
root:__dirname,
verbose:true,
dry:false
}
),
new webpack.optimize.CommonsChunkPlugin({
names:['vendor','manifest']
}),
new HtmlWebpackPlugin({
title:'demo',
template:'index.html'
}),
new UglifyJsPlugin({
beautify:true,
exclude:['/node_modules/'],
compress:{
warnings:false
},
output:{
comments:false
}
})
]
}
整个项目,我们在app文件下的main.js内写业务代码,main.less写样式,在public/index.html下使用热替换进行调试,打包后的压缩文件在public文件夹下,并且对业务代码,第三方代码进行了清晰地区分。
使用这份webpack配置,我们实现了:
- 工程的打包调试
- 公共代码提取,提高开发效率
- 资源压缩
- 热替换
webpack配置实践的更多相关文章
- webpack配置这一篇就够
最近看了一篇好文,根据这个文章重新梳理了一遍webpack打包过程,以前的一些问题也都清楚了,在这里分享一下,同时自己也做了一些小的调整 原文链接:http://www.jianshu.com/p/4 ...
- [webpack] 配置react+es6开发环境
写在前面 每次开新项目都要重新安装需要的包,简单记录一下. 以下仅包含最简单的功能: 编译react 编译es6 打包src中入口文件index.js至dist webpack配置react+es6开 ...
- webpack配置详解
webpack配置详解 先点个赞吧,再挨个点下面的连接,觉得不值这个赞的回来骂我啊. Webpack傻瓜式指南(一) Webpack傻瓜指南(二)开发和部署技巧 Webpack傻瓜式指南 原生的官网详 ...
- Webpack配置示例和详细说明
/* * 请使用最新版本nodejs * 默认配置,是按生产环境的要求设置,也就是使用 webpack -p 命令就可以生成正式上线版本. * 也可以使用 webpack -d -w 命令,生成用于开 ...
- 【转】Flume(NG)架构设计要点及配置实践
Flume(NG)架构设计要点及配置实践 Flume NG是一个分布式.可靠.可用的系统,它能够将不同数据源的海量日志数据进行高效收集.聚合.移动,最后存储到一个中心化数据存储系统中.由原来的Fl ...
- vue-cli#2.0 webpack 配置分析
目录结构: ├── README.md ├── build │ ├── build.js │ ├── check-versions.js │ ├── dev-client.js │ ├── dev-s ...
- [转载] iptables配置实践
原文: http://wsgzao.github.io/post/iptables/ iptables配置实践 By wsgzao 发表于 2015-07-24 文章目录 1. 前言 2. 更新历史 ...
- Zookeeper、Solr和Tomcat安装配置实践
Zookeeper.Solr和Tomcat安装配置实践
- NTP配置实践
前言 NTP(Network Time Protocol,网络时间协议)是用来使网络中的各个计算机时间同步的一种协议.不管是平时使用的私人计算机还是在工作中搭建的服务器集群.时间的统一性和准确性是十分 ...
随机推荐
- 一个简单的ExtJS搜索建议框
封装的是一个Ext4.2的组件,继承并兼容于Ext的ComboBox. 实现原理非常easy,在 combo 中监听 keyup 事件就可以. 搜索建议的Combo.基本上全然兼容, 使用方式与Com ...
- redis数据淘汰策略
概述 在 redis 中,允许用户设置最大使用内存大小 server.maxmemory,在内存限定的情况下是很有用的.譬如,在一台 8G 机子上部署了 4 个 redis 服务点,每一个服务点分配 ...
- XC文件管理器-打造优美易用的文件管理器
技术:Android+java 概述 XC文件管理器,是基于Android6.0+开发的一个方便易用的文件管理器,具有文件的目录管理和文件的管理,主要包括文件的新建.删除.重命名.复制,移动剪切以 ...
- hihocoder第229周:最大连续字母个数
题目链接 给定一个仅包含小写字母的字符串s(长度小于1e5),你可以交换任意两个字符的位置,现在允许交换k次,要求交换之后,s中最长的连续相同字符个数尽量多,求这个最长连续区间的长度. 样例 输入 1 ...
- 1A2B猜数字
知乎链接 维基百科 问题描述 又名猜数字. 一方准备从0到9十个数字里抽出4个数,随机排列,另一方同样以这样的方法回应四个数.位置相同数字相同为A,数字出现,位置不同为B,然后计数. 例1234 56 ...
- ios实例开发精品文章推荐(8.14)
1.iOS源码:俄罗斯方块实现简单的俄罗斯方块游戏.<ignore_js_op> 下载地址:http://www.apkbus.com/android-124628-1-1.html 2. ...
- Hyperscan 介绍与安装【转】
来源:http://blog.sina.com.cn/s/blog_913a533b0102wc38.html Hyperscan 介绍与安装 (2016-01-27 16:22:32) 转载▼ ...
- 关于Apache (httpd)服务器防DDOS模块mod_evasive的使用说明
关于Apache (httpd)服务器防DDOS模块mod_evasive的使用说明 1. mod_evasive 介绍: mod_evasive 是Apache(httpd)服务器的防DDOS的一个 ...
- 通用MYSQL5.5和5.6源码包安装
系统:REDHAT 6.3安装方式:最小化安装1.MYSQL5.5源码安装环境,依懒的安装包 yum install make gcc gcc-c++ ncurses-devel openssl-de ...
- 终极 Shell
在开始今天的 MacTalk 之前,先问两个问题吧: 1.相对于其他系统,Mac 的主要优势是什么?2.你们平时用哪种 Shell?…… 第一个童靴可以坐下了,Mac 的最大优势是 GUI 和命令行的 ...