webpack4 配置
从零搭建webpack工程化项目
1.webpack简介

-
webpack是一个现代JavaScript的模块化的打包工具
-
4个核心概念
- 入口(entry)
- 输出(output)
- loader
- 插件(plugins)
-
3件事
- 搭建webpack项目框架
- 搭建vue模块化开发环境
- webpack打包优化
-
基本知识
webpack,前端工程化,
2. webpack 、gulp区别
1.webpack: 基于模块化打包工具
2.gulp:基于任务流的构建工具
gulp.task('watch', function(cb) {
runSequence(
['copy:img', 'sass', 'include', 'copy:js'],
'dev',
cb
);
});
gulp.task('start', ['clean:dist', 'clean:tmp'], plugins.shell.task([
'concurrently "gulp watch" "npm start"'
]));
gulp.task('debug', ['clean:dist', 'clean:tmp'],plugins.shell.task([
'concurrently "gulp watch" "npm run debug"'
]));
gulp.task('build', function(cb) {
runSequence(
['clean:dist', 'clean:tmp'],
'build:img',
['build:css', 'build:js'],
'build:html',
'clean:tmp',
cb
);
});
3.核心配置
1 entry(入口)
设置文件入口,单文件或者多文件
// entry 单个文件入口
const path = require('path')
module.export = {
entry: './src/main.js'
}
// 多个文件入口,采用对象形式
entry: {
index: path.join(__dirname, 'src/main.js'),
more: path.join(__dirname, 'src/more.js')
}
2. output(出口)
output: {
// 输出名字
filename: 'js/[name].[hash].js', // 采用哈希
path: path.join(__dirname, 'dist')
}
3 loader
- loader是让webpack能够处理非js文件,将其他类型转换为webpack可以处理的有效模块
- loader有rules的两个属性
- test: 正则匹配哪些文件
- use:使用哪些loader
module: {
rules: [
{
test: /\.less$/,
use: [
{loader: 'style-loader'},
{loader: 'css-loader'},
{loader: 'less-loader'}
]
}
]
}
4 plugins(插件)
- 由于插件可以携带参数/选项,你必须在 webpack 配置中,向
plugins属性传入new实例。
// 插件
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'index.html')
}),
// 每次构建前清除dist文件
new CleanWebpackPlugin()
]
4 搭建webpack基本框架
1.项目初始化(webpack-demo)

2.yarn init
3.安装webpack包
yarn add webpack webpack-cli webpack-dev-server webpack-merge --dev
webpack-merge: 可用于合并公共配置和开发配置或者生产配置
4修改package.json,启动脚手架命令 yarn dev || yarn build
"scripts": {
"dev": "webpack-dev-server --config webpack.dev.js --mode development",
"build": "webpack --config webpack.prod.js --mode production"
},
5.webpack.base.js 中为配置公共部分
-
其中require引用,loader引用的需要执行安装·
yarn add xxx --dev -
用到plugins
html-webpack-plugin: 将打包完成的文件内联到生成的HTML文件中clean-webpack-plugin: 每次执行是都清除dist文件 -
安装
yarn add babel-loader@7.1.1 babel-code --dev存在版本问题
const path = require('path');
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {CleanWebpackPlugin} = require('clean-webpack-plugin') // 对象
module.exports = {
// 入口
entry: {
index: path.join(__dirname, 'src/main.js'),
more: path.join(__dirname, 'src/more.js')
},
// 出口
output: {
filename: 'js/[name].[hash].js',
path: path.join(__dirname, 'dist')
},
// loader
module: {
rules: [
{
test: /\.css$/,
use: [
{loader: 'style-loader'},
{loader: 'css-loader'},
],
},
// 配置less
{
test: /\.less$/,
use: [
{loader: 'style-loader'},
{loader: 'css-loader'},
{loader: 'less-loader'}
]
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src')],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]'),
},
},
]
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'index.html')
}),
// 每次构建前清除dist文件
new CleanWebpackPlugin()
]
}
6.webpack.prod.js生产版本配置
- 将
webpack.base.js合并过来
const merge = require("webpack-merge")
const common = require('./webpack.base.js') // 引入公有模块
module.exports = merge(common, {
mode: "production"
})
7.webpack.dev.js开发版本配置
- 将
webpack.base.js合并过来 - 使用
devServer配置端口,加载目录,以及热更新 - 使用热更新插件
webpack.HotModuleReplacementPlugin
const merge = require('webpack-merge') // 引入webpack-merge功能模块
const common = require('./webpack.base.js') // 引入公有模块
const webpack = require('webpack')
// 由于许多不同环境,我们需要抽离公共部分
module.exports = merge(common, {
devServer: {
contentBase: './dist', // 本地服务器加载文件的目录
port: '8899', // 设置端口号
inline: true, // 文件修改后时时刷新
historyApiFallback: true, // 不跳转
hot: true // 热更新
},
// 热更新插件
plugins: [
new webpack.HotModuleReplacementPlugin({
multiStep: true
})
],
mode: "development"
})
这样,一个基本的框架就完成。但是这远远不够,还没有加入现在流行的单页面框架react,vue,接下来,就采用vue来搭建单页面
5添加vue完成搭建
1.安装vue依赖
yarn add vue vue-loader vue-template-compiler --dev
2整改原先项目
-
在
main.js中引入vueimport Vue from 'vue'; import APP from './App.vue'; // 引入App.vue import router from './router'; new Vue({ el: '#app', router, // store, render: h => h(App) }) -
在index.html修改添加
id = app<div id="app"></div> // 解决找不到Cannot find element: #app -
添加
App.vue -
添加
router.js直接使用
component:import('xx')会报错,Unexpected token,可以采用
r => require.ensure( [], () => r (require('../src/component/home.vue')))或者
yarn add babel-plugin-syntax-dynamic-import --dev,修改
webpack.base.js中{ test: /\.js$/, loader: 'babel-loader', // include: [path.join(__dirname, 'src')], exclude : /node_modules/, options: { plugins: ['syntax-dynamic-import'] }, },router.js代码如下:
import Vue from 'vue' import Router from 'vue-router'; // import Home from '../src/component/home.vue' //const Home = r => require.ensure( [], () => r (require('../src/component/home.vue'))) Vue.use(Router) const router = new Router({ mode: 'history', routes: [ { path: '/', name: 'home', component: () => import('../src/component/home.vue') } ] }) router.beforeEach((to, from, next) => { next() }) export default router;这样就完成了基本VUE项目搭建,主要在
webpack.base.jsconst path = require('path'); const webpack = require('webpack') const HtmlWebpackPlugin = require('html-webpack-plugin') const {CleanWebpackPlugin} = require('clean-webpack-plugin') const VueLoaderPlugin = require('vue-loader/lib/plugin.js') module.exports = { // 入口 entry: { index: path.join(__dirname, 'src/main.js'), // more: path.join(__dirname, 'src/more.js') }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js', '@': path.resolve(__dirname, '../src') }, }, // loader module: { rules: [ { test: /\.css$/, use: [ {loader: 'style-loader'}, {loader: 'css-loader'}, ], }, // 配置less { test: /\.less$/, use: [ {loader: 'style-loader'}, {loader: 'css-loader'}, {loader: 'less-loader'} ] }, { test: /\.js$/, loader: 'babel-loader', // include: [path.join(__dirname, 'src')], exclude : /node_modules/, options: { plugins: ['syntax-dynamic-import'] }, }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: 'img/[name].[hash:7].[ext]', outputPath: path.join(__dirname, 'dist/') }, }, { test: /\.(eot|woff|woff2|ttf)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]' } }, { test: /\.vue$/, use: ['vue-loader'] } ] }, // 插件 plugins: [ new VueLoaderPlugin(), new HtmlWebpackPlugin({ template: path.join(__dirname, 'index.html') }), // 每次构建前清除dist文件 new CleanWebpackPlugin(), ], // 出口 output: { filename: 'js/[name].[hash].js', path: path.join(__dirname, 'dist') }, }
6 打包优化
1 分离CSS文件
安装yarn add mini-css-extract-plugin --dev
将style-loader替换成MiniCssExtractPlugin.loader
{
test: /\.(le|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
},
'css-loader',
'less-loader'
]
},
plugins: [
// 输出
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:8].css",
chunkFilename: "css/[id].[contenthash:8].css"
})
]
2 消除冗余css
安装:yarn add purifycss-webpack purify-css glob --dev不太可靠
3 压缩CSS代码
安装yarn add optimize-css-assets-webpack-plugin --dev
// 压缩CSS代码
const optimizeCssAssetsWebpack = require('optimize-css-assets-webpack-plugin')
optimization: {
minimizer: [
new optimizeCssAssetsWebpack({})
]
}
4 压缩JS代码
安装: yarn add terser-webpack-plugin --dev
const terserWebpackPlugin = require('terser-webpack-plugin')
new terserWebpackPlugin({
parallel: 2, // 开启几个进程来处理压缩,
cache: true
})
5 分离不常用的第三方插件
optimization: {
// 分离chunks,不必要第三方
splitChunks: {
chunks: "all",
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: "-", // chunk分隔符
name: true,
cacheGroups: {
// 设置缓存组用来抽取满足不同规则的chunk
element: {
name: "chunk-element-ui",
priority: -9,
chunks: "all",
test: /[\\/]node_modules[\\/](element-ui)/,
reuseExistingChunk: true, // 重复使用已经存在的块
enforce: true, // 强制生成
},
}
},
6 gZip 压缩
安装 yarn add compression-webpack-plugin --dev
// 若已经经过图片或者其他压缩的,gzip压缩不明显
plugins: [
new CompressionPlugin({
// gzip压缩配置
test: /\.js$|\.html$|\.css/, // 匹配文件名
threshold: 10240, // 对超过10kb的数据进行压缩
deleteOriginalAssets: false, // 是否删除原文件
}),
],