1.WebPack基础
1. 概述
1.1 Webpack功能与优势
预处理(TS,Less,Sass,ES6),解析成浏览器识别的css和js
解析文件之间的依赖关系,屏蔽无用文件
图片添加hash,方便线上CDN缓存
模块导入导出
按需加载,有完备的代码分割解决方案
1.2 Webpack简单介绍
Webpack是用Nodejs语法写的,就是CommonJS写的
Webpack 4比3多了mode属性,可以设置development或production
development特性
- 浏览器调试
- 注释、开发阶段的详细错误日志和提示
- 快速和优化的增量构建机制
production特性
- 开启所有的代码优化
- 更小的bundle大小
- 去除掉只在开发阶段运行的代码
Scope hoisting(作用域提升,将多个bundle放到一个闭包里面,可以加快整个代码的运行速度) 和Tree-shaking(打包的结构只包含实际用到的 exports,将无用代码丢弃,减小bundle大小)
去除掉开发阶段运行的代码,比如console :
安装插件:npm install babel-plugin-transform-remove-console --save-dev
然后在项目的babel.config.js的plugin中添加节点。再build就不会有console警告了。
plugins:['transform-remove-console']
这样引入插件后生产环境和开发环境都会去除console,如果只想在生产环境去除console,可以对环境进行判断后引入,优化如下:
if (process.env.NODE_ENV === 'production') {
proPlugins.push('transform-remove-console');
}
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins:[
...proPlugins
]
}
Npm和Yarn都是包管理器
mkdir 目录 可以创建目录
cd 目录 进入目录
创建package.json文件
npm init
安装http-server可以启服务,一般项目中不用,只是了解
启服务命令:http-server test,test为目录
1.3 webpack命令
安装webpack: npm install webpack-cli -g
webpack安装之后具有webpack命令
将文件打包导出方式:
// webpack 导出文件 output 输入目录以及文件名 –mode mode类型
webpack src/test.js --output test/test.js –mode none
mode不设置会压缩文件,相当于production行为;设置为none就不会压缩,相当于development行为。
webpack4新特性中可以不使用配置文件:
webpack --mode development 可以直接进行项目打包,默认打包src中的index.js到dist中的main.js
2. 打包配置以及webpack-dev-server
2.1 配置文件打包模块概述
Webpack配置文件就是webpack.config.js
引入:
var webpack = require('webpack');
var path = require('path');
var DIST_PATH = path.resolve(__dirname,'../dist');
配置文件内部结构:
module.exports = {
// 入口js文件
entry: path.resolve(__dirname,'../src/index.js'),
// 编译输出的路径
output:{
path: DIST_PATH,
filename:'index.js',
}
// 模块解析—预处理ts/less等
module:{}
// 插件
plugins:[]
// 开发服务器
devServer:{},
// 指定打包模式,开发模式还是生产模式,指定后就不用在打包命令中再指定了
mode:development
}
根据配置文件打包命令:
// webpack.config.js中配置了mode,此处就不需要配置了
webpack --config build/webpack.config.js –mode development
打包命令简化:
可在package.json文件中scripts模块中配置
'scripts': {
'build': 'webpack --config build/webpack.config.js –mode production'
}
配置完之后就可以直接通过npm run build直接打包了
2.2 webpack-dev-server 用于配置开发服务器
安装:npm install webpack-dev-server -D
配置文件 webpack.config.js 中的 devServer 中配置该服务:
hot:true,//热更新
contentBase: DIST_PATH, //热启动文件的文件路径
port:8080, //服务端口
host:'0.0.0.0',//表示可以再服务器外部或者localhost或者IP地址都可以访问
historyApiFallback:true,//项目中的404响应都会替换为index.html
open:true, // 服务启动完成之后自动打开浏览器
useLocalIp:true, // 自动打开浏览器的时候使用自己的IP
proxy:{ // 代理:处理跨域访问接口问题
'/api':'http://localhost:3000' //表示接口中有api的时候就会代理到http://localhost:3000
},
https:true, // 如果需要https访问接口的话,需要进行该配置
简化启服务的命令如同上面打包一样,需要到package.json文件的scripts模块中配置
'scripts': {
'dev': 'webpack-dev-server --config build/webpack.config.js –mode production'
}
表示启服务的时候使用webpack.config.js中的配置,使用上面打包的相同配置
命令简化为npm run dev
此时服务启动之后就可以通过http://localhost:8080/index.js访问了,但是dist的文件下面没有index.js文件却还能访问,原因在于启服务打包的文件都在内存中。为什么内存文件在dist目录下面,因为contentBase配置的就是这个目录。此时如果文件有更新就会立刻反应到我们访问的内存服务页面中,原因在于我们配置了hot。
3.开发环境和生产环境配置
由于生产环境和开发环境的配置是有差异的,使用同一个配置文件会有一些不方便,所以将webpack.config.js分离成三个js配置文件使用
3.1安装webpack-merge
安装: npm install webpack-merge -D
webpack-merge是一个方法,可以传入多个参数,会将多个参数合并成一个对象,如果有重复的属性名,后面的会覆盖前面的
3.2分离文件
// config目录下面添加三个文件
webpack.base.js // 公共配置
webpack.dev.js // 开发环境的配置
webpack.pro.js // 生产环境的配置
webpack.base.js内容:
module.exports = {
// 入口js文件
entry: path.resolve(__dirname,'./src/main.js'),
// 编译输出的路径
output:{
path: path.json(__dirname,'../dist'),
filename:'index.js',
}
// 模块解析—预处理ts/less等
module:{}
// 插件
plugins:[]
}
webpack.pro.js内容:
const base = require('./webpacl.base.js')
const merge = require('webpack-merge')
module.exports = merge(base,{
mode:'production',
})
webpack.dev.js内容:
const base = require('./webpacl.base.js')
const merge = require('webpack-merge')
module.exports = merge(base,{
mode:'development',
devServe: {
port: 8080, // 配置端口号:8080
open: true // 自动打开浏览器
}
})
3.3配置package.json
'scripts': {
'build': 'webpack --config config/webpack.pro.js'
'dev': 'webpack-dev-server --config config/webpack.dev.js'
}
4.多入口文件打包配置
4.1文件打包的入口方式
方式1:打包单个文件,打包结果是单个文件
entry: path.resolve(__dirname,'../src/index.js')
方式2:数组,打包出来会合并成单个文件
如果文件打包需要打包index.js和test.js两个文件,入口文件配置项entry写法可以改成
var SRC_PATH = path.resolve(__dirname,'../src');
entry:[SRC_PATH +'/index.js',SRC_PATH +'/test.js']
方式3:对象,打包结果是多个文件,文件名就是entry中对象的键名
entry:{
index:SRC_PATH +'/index.js',
test:SRC_PATH +'/test.js'
}
output:{
path: DIST_PATH,
filename:'js/[name].js',
}
4.2文件打包hash配置
由于线上会做cdn缓存,一旦功能或者其他文件有修改,打包更新到线上后,很可能修改不会产生作用,所以我们要对文件进行hash处理
方式1:hash全局更新,一旦某一个文件有更新,所有文件都一起重新生成更新,每次生成的所有文件hash部分名字都一样,cdn缓存就等于失效了
output:{
path: DIST_PATH,
filename:'[name].[hash].js',
}
方式2:chunkhash局部更新,只更新修改的文件,并且文件的hash部分是全局唯一的,起到cdn的缓存作用
output:{
path: DIST_PATH,
filename:'[name].[chunkhash].js',
}
// chunkhash默认20位hash值打包,如果想配置成5位hash值文件
output:{
path: DIST_PATH,
filename:'[name].[chunkhash:5].js',
}
方式3:contenthash,从js里面抽出css文件
4.3glob插件实现动态配置
如果入口文件太多,配置项比较麻烦,可以通过glob插件完成
var glob = require('glob');
var SRC_PATH = path.resolve(__dirname,'../src');
var entryFiles = {};
// 通过glob的sync方法找到所有的同步文件,他的参数可以是正则表达式,返回所有找到的文件路径
var files = glob.sync(path.join(SRC_PATH,'/**/*.js'));
files.foreach(function(file,index){
var subkey = file.match(/src\/(\S*)\.js/)[1];
entryFiles[subkey] = file;
})
entry:entryFiles,
4.4提取公共模块配置
当多入口文件输出多个文件时,都引入了JQuery,那两个输出文件都包含JQuery引入,没必要且负面影响很多,可以通过optimization.splitChunks插件(webpack4之前单独插件,之后webpack内置了)的chunks属性设置为all来优化,这样公共部分的JQuery就会被提取出来单独作为一个js被引用
公共模块大小必须大于30kb才会被独立打包,打包出来的文件名是可以设置的
module.exports = {
// 与entry、output并列
// 优化打包配置的集合
optimization: {
splitChunks: {
// 提取所有文件的共同模块
chunks: 'all'
}
}
};
5.webpack编译html文件
5.1引入插件html-webpack-plugin打包html文件
安装:npm install html-webpack-plugin -D
// 引入插件
var htmlWebpackPlugin = require('html-webpack-plugin');
// plugins中配置插件
plugins:[
new htmlWebpackPlugin({
filename:DIST_PATH+'/index.html',// 文件打包到哪里
title: '我的第一个测试',// 打包文件的title是可以通过这个参数传递的,通过<head><%=htmlWebpackPlugin.options.title %></head>读取
template:SRC_PATH+'/pages/index.html',// 模板,也就是原文件路径
inject:true,// true和body表示将生成的js文件插入到body的底部,head表示插入到head的底部,false表示不插入生成的js文件,默认true
hash:true,// 会给页面上引入的js文件加上hash值
minfy:true,// 是否对打包的文件进行压缩
chunks:['index','common'],// 按需引入js文件,不存在的js文件会自动过滤不引入,默认将所有生成的js文件都引入到html内
})
]
5.2多入口html文件打包
方式1:添加多个htmlWebpackPlugin对象
plugins:[
new htmlWebpackPlugin({
filename:DIST_PATH+'/index.html',// 文件打包到哪里
title: '我的第一个测试1',// 打包文件的title是可以通过这个参数传递的,通过<head><%=htmlWebpackPlugin.options.title %></head>读取
template:SRC_PATH+'/pages/index.html',// 模板,也就是原文件路径
inject:true,// true和body表示将生成的js文件插入到body的底部,head表示插入到head的底部,false表示不插入生成的js文件,默认true
hash:true,// 会给页面上引入的js文件加上hash值
minfy:true,// 是否对打包的文件进行压缩
chunks:['index','common'],// 按需引入js文件,不存在的js文件会自动过滤不引入,默认将所有生成的js文件都引入到html内
}),
new htmlWebpackPlugin({
filename:DIST_PATH+'/test.html',// 文件打包到哪里
title: '我的第一个测试2',// 打包文件的title是可以通过这个参数传递的,通过<head><%=htmlWebpackPlugin.options.title %></head>读取
template:SRC_PATH+'/pages/test.html',// 模板,也就是原文件路径
inject:true,// true和body表示将生成的js文件插入到body的底部,head表示插入到head的底部,false表示不插入生成的js文件,默认true
hash:true,// 会给页面上引入的js文件加上hash值
minfy:true,// 是否对打包的文件进行压缩
chunks:['test'],// 按需引入js文件,不存在的js文件会自动过滤不引入,默认将所有生成的js文件都引入到html内
})
]
方式2:利用glob循环添加多文件打包的html
var glob = reuqire('glob');
var htmlWebpackPlugin = require('html-webpack-plugin');
var DIST_PATH = path.resolve(__dirname,'../dist');
var SRC_PATH = path.resolve(__dirname,'../src');
var pluginAll = [];// 放所有的插件
// 通过glob的sync方法找到所有的同步文件,他的参数可以是正则表达式,返回所有找到的文件路径
var pages = glob.sync(path.join(SRC_PATH,'/pages/**/*.html'));
pages.foreach(function(page,index){
var pagename= page.match(/src\/pages\/(\S*)\.html/)[1];
var plug = new htmlWebpackPlugin({
filename:DIST_PATH+'/'+pagename+'.html',// 文件打包到哪里
title: '我的第一个测试'+index,// 打包文件的title是可以通过这个参数传递的,通过<head><%=htmlWebpackPlugin.options.title %></head>读取
template:SRC_PATH+'/pages/'+pagename+'.html',// 模板,也就是原文件路径
inject:true,// true和body表示将生成的js文件插入到body的底部,head表示插入到head的底部,false表示不插入生成的js文件,默认true
hash:true,// 会给页面上引入的js文件加上hash值
minfy:true,// 是否对打包的文件进行压缩
chunks:[pagename],// 按需引入js文件,不存在的js文件会自动过滤不引入,默认将所有生成的js文件都引入到html内
})
pluginAll.push(plug);
})
plugins: pluginAll,

浙公网安备 33010602011771号