简介
webpakc的定位实际上是打包器.而不是任务执行器.
当然也可以配合grunt进行使用.
webpack也提供了便捷的打包流程,项目构建,插件管理等等.
为了更好的构建项目从开发到生产都一一提供了解决方案.
Vue官方也推荐使用的vue-loader也是基于webpack的.
因此这里简单介绍一下webpack的使用一些总结.更详细细致的内容可以到官网进行拓展.
安装
局部安装
使用命令行的安装方式 :
npm install --save-dev webpack
我们可以写到配置文件当中package.json
,对应的目录中然后再执行npm install
{
"name": "XXXX",
"version": "1.0.0",
"description": "XXX",
"author": "XXX",
"private": true,
"scripts": {//指定执行命令
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"watch":"webpack --watch",
"build": "webpack --config webpack.prod.js",//也可以进行自定义
"debug": "nodemon build/build.js"
},
"dependencies": {
"swiper": "^4.0.7",
"vue": "^2.5.2",
"vue-router": "^2.8.1",
"element-ui": "2.2.1"
},
"devDependencies": {
}
}
全局安装
npm install --global webpack
工程结构
我们可以根据项目的实际的情况设置目录.
一般情况下可以设置为源码目录,生产目录.
我们可以将webpack配置文件与package.json放入到项目的根目录.
webpack配置文件
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
目录结构如下:
webpack-demo
|- package.json
|- webpack.config.js
|- /dist
|- bundle.js
|- index.html
|- /src
|- index.js
|- /node_modules
资源管理
这里先简单介绍下CSS资源的管理配置.
安装loader,loader的作用就是将文件进行处理(编译,压缩).
npm install --save-dev style-loader css-loader
module.exports =
{
module: {
rules: [
{
test: /\.css$/, //指定匹配文件,使用style-loader,css-loader
use: [
'style-loader',
'css-loader'
]
}]
}
}
输出管理
输出管理的目的是为了更好的简化工作.
我们可以使用插件,输出js名字更替等
webpack当中有许多的插件我么可以将其进行更替.
这边先简单介绍两个插件 生成html的插件,清除目录的插件.
npm install clean-webpack-plugin --save-dev
npm install --save-dev html-webpack-plugin
整个配置文件,注意插件的配置顺序.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
plugins: [
new CleanWebpackPlugin(['dist']),//清除dist目录
new HtmlWebpackPlugin({ //生成一个html页面指定其title,然后会自动将js文件生成引入js代码
title: 'Output Management'
})
],
output: {
//publicPath:XXX 可以资金定义路径,build后输出的内容将会放入到这个路径当中
filename: '[name].bundle.js', //注意name用方括号括起来,name的值对应的为entry的key值,这样为了区分多个文件
path: path.resolve(__dirname, 'dist')
}
};
开发工具
webpack 最强大的是开发提供的开发工具
webpack-server 提供了访问页面的服务
webpack-watch 提供了观察文件的变化
webpack-dev-middleware webpack-server内部也是采用了该方法,不仅如此,也提供了其它的自定义的功能很强大.
配置文件
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
devtool: 'inline-source-map',
//devServer: {
// contentBase: './dist'
//},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Output Management'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'//middleware会用到该路径,url访问的路径
}
};
在dist同级目录添加server.js
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
// Serve the files on port 3000.
app.listen(3000, function () {
console.log('Example app listening on port 3000!\n');
});
HRM
HRM是hot replacement module,主要是启动服务后文件可以进行热更新,例如css样式或者js等文件变更,会自动更新到页面上.只能用于开发环境不能用于生产环境.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
+ const webpack = require('webpack');
module.exports = {
entry: {
app: './src/index.js'
},
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
hot: true
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']//style-loader插件使对于CSS文件进行实时渲染
}
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Hot Module Replacement'
}),
new webpack.NamedModulesPlugin(),//添加该插件更容易观察依赖文件被更新
new webpack.HotModuleReplacementPlugin()//动态替换文件
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Vue-Loader
.vue 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 <template>
、<script>
和 <style>
,还允许添加可选的自定义块:
<template>
<div class="example">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style>
.example {
color: red;
}
</style>
<custom1>
This could be e.g. documentation for the component.
</custom1>
生产环境
我们可以指定生产环境的配置,可能第三方库会使用到该变量.
因此最好添加如下配置到配置文件的入口.
process.env.NODE_ENV = 'production'
webpack 配置可以提炼出来,使用webpack-merge
将webpack的配置文件进行合并.
我们可以建一个webpack.common.js
文件,然后创建一个webpack.prod.js
,webpack.dev.js
,那么可以将prod,dev引入common共同引用参数.
common文件
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Production'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
生产环境:
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');
module.exports = merge(common, {
plugins: [
new UglifyJSPlugin()
]
});
开发环境:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
}
});
代码管理
默认的情况下,webpack会把引用的文件都会build到单独的文件当中.我们可能会把一些第三方的模块放到一个单独文件里.
需要对配置文件做如下改动:
//plugins数组当中添加一下参数
new webpack.optimize.CommonsChunkPlugin({
name: 'common' // Specify the common bundle's name.
})
这样配置后,例如两个js文件中共同的import XX from './underscore.js'
那么underscore被多个包导入后,不会被每个js文件引入,而放入到配置文件当中所配置的common.js
文件
缓存策略
我们可以根据http协议告知浏览器是否进行缓存,例如:ETag,If-modified-since,Cache-Control等
webpack也提供了便利的hash方法进行资源的访问.
hash:每次build相关的hash
chunk hash : 在文件名中包含一个 chunk 相关(chunk-specific)的哈希。
配置当中output添加chunhash
output: {
filename: 'bundle.js',
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist')
}
有时候我们可能不需要每次编译生成相同的文件却生成了不同的hash.
还有个问题webpack默认的hash是根据module.id以及内容生成,而module.id根据解析文件的顺序生成,一个重要的问题是每次改动引入的文件,就可能会造成其它文件hahs不一致.
这时候就需要HashedModuleIdsPlugin插件,指定使用Path以及内容作为hash的内容.
只需要配置文件当中在plugins增加如下配置:
plugins:[
...,
new webpack.HashedModuleIdsPlugin(),
...
]
垫片
当我们需要全局引入一个变量,webpack不推荐这样做应为会影响到模块化编程.
如果的确需要这样做的时候,我们可以使用ProvidePlugin
plugins: [
new webpack.ProvidePlugin({
_: 'lodash'
})
]
每个js文件就不需要去import引入对应的代码.
我们或许只需要部分第三方库的功能,我们可以这样进行配置
plugins: [
new webpack.ProvidePlugin({
_: 'lodash',
join:['lodash', 'join']//我们可以这样进行配置 ['module', 'child', 'child']
})
]