项目准备
项目地址
项目结构
1 2 3 4 5 6 7 8 9
| - src - app - App.vue - img - logo.png - style - app.scss - index.html - main.js
|
webpack基本概念
entry
即webpack打包的入口js文件,可以根据项目实际情况配置成但入口或者多入口,webpack会根据入口文件内的引入的文件绘制依赖图,将该模块和模块对应的依赖都打包到一个文件中。
1 2 3 4 5 6 7 8 9 10 11
| //单入口 const config = { entry:'a.js' } //多入口 const config = { entry:{ a:'a.js', b:['b1.js','b2.js'] //多个文件打包为一个文件 } }
|
output
即webpack打包后的输出,即使此时的entry中存在多个入口,也只提供单一的输出配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| //单一入口情况,一下将所有文件都打包到dist/bundle.js里 const config = { output:{ filename:'bundle.js', path:path.join(__dirname,'dist') } } //多入口情况 const config ={ output:{ filename:'[name].js', path:path.join(__dirname,'dist') } }
|
这里的输出文件名中可以使用[name],[hash],[chunkhash]等占位,这样输出的文件名中就有带有资源hash值。[hash]是本次打包所有资源的hash值,同义词打包的文件得到的hash是一样的,而[chunkhash]是单个文件打包的hash值,每个文件且每次打包都不相同。还可以使用[hash:8]来取hash值得位数
Loader
webpack是一个js bundler,如果需要它对非js得模块,例如typeScript,sass,less,vue等模块进行打包,则需要对应的loader进行转换。而且同一种资源有时需要使用不止一种loader。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const config ={ module:{ rules:[ { test: /\.vue$/, use: [{loader: 'vue-loader'}] }, { test:/\.scss/, use:[ {loader:'style-loader'}, { loader:'css-loader', options: { modules: true } }, {loader:'sass-loader'} ] } ] } }
|
在rules数组中的每一项都是一种模块类型的转换规则,test参数匹配对应后缀的文件,use数组中配置对应使用的loader以及配置loader的其他参数。
官方推荐的loader
Plugins
plugins用于解决其他loader无法做到的事情,比如压缩资源,启动开发服务器等等。
1 2 3 4 5 6 7 8 9 10 11
| const HtmlWebpackPlugin = require('html-webpack-plugin'); const path = require('path');
const config ={ plugins:[ new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({ template:path.join(__dirname,'src/index.html') }) ] }
|
plugins数组的每一项就是一个插件
webpack自带的以及推荐使用的Plugins
webpack配置文件结构
webpack默认的配置文件名为webpack.config.js,当然也可以自定义其他文件名,只要在webpack –config filename命令中修改filename为当前的配置文件即可。
完整的webpack配置参数可以查看官方文档
开发模式和打包模式(Dev&Build)
可以通过命令行向webpack闯入参数,以判断使用开发模式还是打包。
在package.json中配置npm script:
1 2 3 4
| "scripts": { "build": "cross-env NODE_ENV=production webpack --config webpack.config.js", "dev": "cross-env NODE_ENV=develement webpack-dev-server --config webpack.config.js" }
|
命令行中使用了cross-env用于跨平台地设置及使用环境变量,具体的参照官方github说明
在build和dev中我们分别向webpack传入了不同的NODE_ENV参数值。在webpacl配置文件中,可以使用process.env.NODE_ENV来的到这个值,以便判断该运行那哪个模式。
webpack-dev-server
在webpack中用devServer参数来配置它,在此之前我们需要先判断是否运行在开发模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| var WebpackDevServer = require('webpack-dev-server');
//获得NODE_ENV参数,用于判断处于开发模式还是打包模式 var isDev = process.env.NODE_ENV === 'develement';
const config = { .... }
if(isDev){ //webpack-dev-server不能使用chunkhash,否则会报错 config.output.filename ='[name]-[hash].js'; config.devtool = '#cheap-module-eval-source-map';
config.plugins.push( new webpack.HotModuleReplacementPlugin(), //热更新插件 new webpack.NoEmitOnErrorsPlugin() //防止错误信息导致webpack退出 )
//启动开发服务器 config.devServer={ contentBase:path.join(__dirname,'dist'), compress:true, //启用gzip压缩 port:8080, hot:true, //启用webpack热模块替换特性 open:true //是否在开始服务器后打开浏览器 } }
|
在devServer中配置hot:true并不在代表已经启用了热模块替换,还需要使用webpack.HotModuleReplacementPlugin插件才能生效,hot仅仅是一个开关
单独打包css文件
想vue文件中的样式通常会被打包进js文件中,在该组件被加载时同时加载样式。而有一些公共的样式通常会写在单独的文件中,如果我们在多个组件中引用公共样式,那么公共样式会在多个js模块中被打包,这样会增加文件的体积。这是应该将这些公共样式提取出来单独打包。
这里我们使用extract-text-webpack-plugin插件来提取公共样式,所以此时我们的配置文件中就该改为这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| var ExtracTextPlugin = require('extract-text-webpack-plugin');
const config ={ module:{ rules:[ { test: /\.scss/, use: ExtracTextPlugin.extract({ use: [{ loader: 'css-loader' }, { loader: 'sass-loader' }] }) } ] }, plugins:[ new ExtracTextPlugin('style-[contentHash:8].css') ] }
|
这样就能将scss文件单独打包了
提取公共模块
同理我们在项目中使用类库,也需要单独打包,以防止重复加载,节省流量。
这里使用的是webpack自带的插件CommonsChunkPlugin,在entry中添加vendor模块,然后在插件中配置单独打包vue。
1 2 3 4 5 6 7 8 9 10 11
| var config = { entry: { app:path.join(__dirname, 'src/main.js'), vendor:['vue'] }, plugins:[ new webpack.optimize.CommonsChunkPlugin({ name:'vendor' }) ] }
|