前言
从webpack3
一路到webpack4
,刚开始一直抱着搭起来能用的态度.直到开始工作,大大小小的项目接触了四五个,慢慢有了一个适合自己使用的脚手架.在开发过程中有遇到很多不顺手的地方:
由于项目需要,开发以及部署时的后台
ip
地址经常在变化,开发时会抽出一个单独的js
文件定义所有这些外部的地址,便于管理.但是在打包之后就被webpack
打包了,如果要修改地址又要重新打包,过于繁琐.个人喜欢
less
,但是less
不能自定义函数,以及无法定义全局的变量
.比如想在variable.less
中定义页面公用的一些变量,方便后期调整页面布局.但是需要在每个用到这些变量的.vue
文件中单独引入,太过累赘.
慢慢的解决问题,直到我发现我的webpack.config.js
居然有四五百行代码,这太乱了.于是决定重新在构造一个项目脚手架,进行优化.
重修之路
创建项目基础结构,一步一步慢慢添加
├── dist // 打包后目录
├── src
│ ├── assets // 全局的静态文件,无法打包时
│ │ └── img
│ ├── config // 数据后台IP地址配置文件
│ │ └── ip.config.js
│ └── index.js // 入口文件
├── package.json
└── webpack.config.js // webpack配置文件
先了解几个webpack插件
-
clean-webpack-plugin
: 每个打包之前清理dist
文件夹 -
copy-webpack-plugin
: 复制文件或者文件夹到打包目录 -
html-webpack-plugin
: 生成html
模板以及自动引入打包后文件
我们希望assets/
下的文件原封不动的复制到dist/
目录下,比如有一些图片webpack
无法打包时,我们就在assets
下新建一个img
文件夹,把这些图片放进去,打包时copy-webpack-plugin
就会自动就img
整个文件夹复制到dist
对于config/
,打包后我希望它一样是在dist/config
下.
然后我们需要在html
文件中加入script
标签引入dist/config
目录下所有的.js
文件
- 安装
npm i -D copy-webpack-plugin clean-webpack-plugin html-webpack-plugin
- 使用
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin([
{from: 'src/config/*.js', to: 'config/', toType: 'dir', flatten: true},
{from: 'src/assets/', toType: 'dir'}
]),
new HtmlWebpackPlugin({
inject: false,
template: require('html-webpack-template'),
title: '测试输出',
appMountId: 'app',
meta: [
{
name: 'viewport',
content: 'width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0'
}
],
bodyHtmlSnippet: ""
})
]
...
}
- 说明
clean-webpack-plugin
使用是非常简单的,默认就是删除dist
文件夹,安装引入之后,直接在plugins
实例化即可.
copy-webpack-plugin
使用
-
from
:定义操作目标 -
to
: 复制到dist
文件夹下的哪里 -
toType
: 类型, 文件或者文件夹` -
flatten
: 是否按照本来的目录复制, 默认是false
下面再说说最强大的html-webpack-plugin
,会自动生成html
模板,也可以以自己定义的html
文件为模板
必须的参数
inject
: false,
template
:html
文件,如果是自己定义的则是文件所在路径可选参数
title
: 标题,
appMountId
: 插入的div
的id
meta
:meta
选项
headHtmlSnippet
: 插入head
的html
模板,这里我们需要插入config
目录下所有的js
文件, 所以我们需要定义一个函数,如果config
目录下文件多的话我们手动一个一个去加就太浪费时间了,而且效率太低,加一个就要改一次配置
/**
* 获取script标签字符串
* @param {String} source [源目标目录]
* @param {[String]} targetDir [生成的文件夹]
* @return {[String]} [指定文件夹下的js文件的script标签]
*/
function getConfigScript(source, targetDir) {
let configFiles = fs.readdirSync(source, {});
let jsFiles = configFiles.filter( file => {
return file.indexOf('.js') !== -1;
})
let scripts = jsFiles.map( file => {
return ``
})
return scripts.join('\n');
}
改html-webpack-plugin
的bodyHTMLSnippet
bodyHtmlSnippet: getConfigScript('./src/config', 'config/')
- 打包一下,看看我们生成的是什么
├── config
│ └── ip.config.js
├── img
│ └── test.png
├── index.html
└── js
└── app.bundle.js
看一下index.html
测试输出
到现在我们已经成功实现了初始的基础需求了.
更多html-webpack-plugin配置
但是我们使用webpack
往往不止会用来打包js
还有css
,img
等等,如果我们都写在一个文件里的话代码就会越来越多,到最后可读性会越来越差,而且不利于阅读以及再次复用,并且开发环境以及生产环境有一些配置是不用的,所以我们将不同的配置代码拆开为dev
以及prod
,公用的定义为common
.我们可以使用webpack-merge
合并不同环境下的配置
- 新建一个
script
文件夹用来存放配置脚本, 将现在的webpack.config.js
改为webpack.common.js
, 新建webpack.dev.js
和webpack.prod.js
- 修改
npm
启动脚本
"scripts": {
"start": "webpack-dev-server --open --config script/webpack.dev.js",
"build": "webpack --config script/webpack.prod.js"
}
开发模式
- 开启
devtool
的source-map
便于调试 - 使用
webpack-dev-server
// webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
module.exports = merge(common, {
mode: 'development',
output: {
publicPath: '/'
},
devtool: 'source-map',
devServer: {
contentBase: './dist',
host: '0.0.0.0',
port: 8001,
index: 'index.html',
open: true,
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
})
生产模式
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production'
})
webpack
生产模式下会自动对js
文件进行压缩混淆,但是我们还希望对图片以及css
文件进行处理.