webpack详解
概念
官网上这么解释webpack的,“webpack 是一个用于现代 JavaScript 应用程序的_静态模块打包工具_。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle。”
作用
代码转换
js es6代码转成es5
@babel/core @babel/preset-env @babel/polyfill
autoprefixer
css loader对sass less等的转换
文件优化 图片处理
压缩代码体积
optimize-css-assets-webpack-plugin
uglifyjs-webpack-plugin
去除console debugger 调试标识等
代码分割
公共模块的抽离
懒加载
模块合并
多个模块合成一个模块
服务部署
本地启动服务 热更新 解决跨域问题
webpack-dev-server
代码校验
eslint代码校验
自动发布
打包完成自动发布
基础配置
配置webpack.config.js文件
// path: Node.js 核心模块,用于操作文件路径。
const path = require('path');
//将打包好的文件更新到html模板中
const HtmlWebpackPlugin = require('html-webpack-plugin');
//抽离css的插件
const MiniCssExtractPlugin = require('mini-css-extrac-plugin');
// autoprefixer 自动填充css3前缀
//压缩css
let optimize = require('optimize-css-assets-webpack-plugin');
// 压缩js
let UglifyJsPlugin = require('uglifyjs-webpack-plugin');
let webpack = require('webpack');
// babel转es5 babel-loader @babel/core @babel/preset-env @babel/polyfill
/*
exporse-loader 把变量暴露全局的方式
内联的loader
pre 前置执行loader
normal 普通loader
post后置loade
*/
//file-loader 会生成图片到build下 并把路径返回 适用于import引入图片
// html-withimg-loader 适用于html img引入图片
// url-loader 做图片限制 小于多少用base64转化
//cleanWebpackPlugin
//copyWebpackPlugin
//bannerPlugin 内置插件
module.exports = {
//优化项
optimization: {
minimizer: [
new UglifyJsPlugin(
{
//添加缓存
cache: true,
//开启并发压缩
parallel: true,
//源码映射,方便调试
sourceMap: true
}
),
new optimize()
]
},
devtool: 'source-map', //增加映射文件 可以帮我们调试源代码 有单独的文件
//devtool: 'eval-source-map', //不会产生单独的文件 但是会显示行和列
//devtool: 'cheap-module-source-map', //产生后可以保留起来 不会显示行和列
//devtool: 'cheap-module-eval-source-map', //没有行跟列 跟html集成 不会产生单独的文件
//打包时有两种模式,分别为:production 和 development
mode: '',
//打包的入口
entry: './path/to/my/entry/file.js', //单页打包
// entry: {
// home: './path/to/my/entry/file.js',
// other: './path/to/my/entry/file.js'
// },
//多页打包
// path: 打包后的文件输出路径
// filename: 打包后的文件名称
watch: true,
watchOptions:{
poll: 1000, //每秒询问频次
aggreatement: 500, //防抖
ignored: /node_modules/ //不需要进行监控的文件
},
output: {
//path.resolve 将路径解析为一个绝对路径
path: path.resolve(__dirname, 'dist'),
filename: 'webpack.bundle.[hash].js',
publicPath: 'www.img.com' //公共路径
},
// 开发服务器的配置 需要添加 webpack-dev-server
devServer: {
port: 3000, //服务启动端口
progress: true, //是否展示进度条
contentBase: 'path', //指向文件路径
compress: true, //启动文件压缩
},
plugins: [ //webpack 所有的插件
new HtmlWebpackPlugin({
template: path, //模板地址
filename: index.html, //打包后文件
minify: { //将打包后的文件最小化
removeAttributeQuotes: true, //去掉所有双引号
collapseWhitespace: true //将代码折成一行
},
hash: true // 加上hash值 避免出现缓存
}),
new MiniCssExtractPlugin({
filename: min.css //打包后文件
}),
new webpack.ProvidePlugin({ //在每个模块中都注入$
$: 'jquery'
})
],
externals: {
jquery: $
}, //外部引入 不需要打包
//样式处理 默认只能解析js 并不能解析css
module: {
noParse: /jquery/, //不去解析jquery依赖包
//loader 全局变量引入
rules: [
{
test: /\.(png|jpg|gif)$/,
// use: 'file-loader'
use: {
loader: 'url-loader',
options: {
limit: 200*1024,
outputPath: '/img/'
}
}
},
{
test: /\.html$/,
use: 'html-withimg-loader'
},
{
test: require.resolve('jquery'),
use: 'expose-loader?$!jquery'
},
//css loader 解决 @import语法
// style-loader 把css插入head标签中
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, //如果单独抽出来需要配置此项
{
loader: 'style-loader',
options: {
insertAt: 'top' //解析好的文件插入位置
}
},
'css-loader',
'postcss-loader',
]
},
{
test: /\.js$/, //新建文件在.eslintrc.json 配置eslint配置
use: {
loader: 'eslint-loader',
options: {
enforce: 'pre', // previous 强制这个loader在之前执行 post 在之后执行
}
},
},
{
test: /\.js$/,
use: {
loader: 'bable-loader',
options: { //用babel-loader需要把es6转es5
presets: [ //预设
'@babel/prest-env',
],
plugins: [
'@bable/plugin-proposal-class-properties', //支持class声名
//generator
// 装饰器 等 去官网上自己找plugins吧 附在网址 https://babeljs.io/
]
},
},
include: path.resolve(__dirname, 'src'), //需要打包的路径
exclude: /node_modules/, //不需要打包的路径
}
]
},
// 跨域配置
devServer:{
before(app){}, //做数据mock
proxy: {
// '/api': 'http://localhost:3000' //代理配置
'/api':{
target: 'http://localhost:3000',
pathRewrite:{'/api': ''}, //重新请求
}
}
},
resolve: { //解析第三方包
modules: [path.resolve('node_modules')],
alias:{ //别名
bootstrap: 'dist/css/bootstrap.css'
}
}
};
postcss.config.js
module.exports = {
plugins: [require('autoprefixer')]
}
打包过程
打包一个文件时,首先会检查打包的文件是否在缓存(installedModules对象)中,如在缓存,直接返回,如不在缓存进行打包相关操作(modules[moduleId].call(module.exports, module, module.exports, webpack_require_))
返回打包后的文件 (return modules[moduleId] )
更改webpack 配置文件命令
webpack --config webpack.config.my.js
引入第三方包的方式
1、expose-loader 挂在window上
2、providePlugin 给每个模块注入
3、cdn引入 可以引入不进行打包 externals
抽离公共代码
第三方与公共代码的抽离
optimization:{
slitChunks: {
cacheGroups:{
commmon: {
chunks: 'initial',
minSize: 0, //最小大小
minChunks: 2 //用过多少次去提取公共包
},
vendor: {
priority: 1,
test: /node_modules/,
chunks: 'initial',
minSize: 0, //最小大小
minChunks: 2 //用过多少次去提取公共包
}
}
}
}
懒加载
添加动态载入插件 plugin-syntax-dynamic-import
//原理
import('test.js').then();
热更新
new webpack.NamedModulesPlugin() //打印更新的模块
new webpack.HotModuleReplacementPlugin() //热更新
if(module.hot){
module.hot.accept('./source', ()=>{
console.log('update');
let str = require('source');
console.log(str);
})
}
好了,webpack的基础配置就到这里了,下一章偏原理些。