webpack配置相关
webpack默认支持commonjs规范和esmodules规范webpack-cli可以解析用户传递的参数- 浏览器无法识别
require(),module.exports,所以需要webpack打包解析
webpack webpack-cli 0配置的方式打包
执行方式:
- 第一种:当前目录下:
npx webpack(npx 可以执行当前node_modules/.bin目录下的文件;两个模式: 开发模式,生产模式;npx webpack --mode development开发模式下打包出的文件不会被压缩,生产模式会压缩和优化)
- 第二种:在
package.json文件配置
"scripts":{
"dev":"webpack --mode development",
"bulid":"webpack --mode production"
}
执行
npm run build时,会暂时将当前node_modules/.bin目录下的文件放在全局环境变量下,执行完销毁
webpack配置文件
配置文件默认名字:webpack.config.js,webpack.file.js
package.json文件
"scripts":{
"dev:build":"webpack --env.development --config ./build/webpack.base.js",
"dev":"webpack-dev-server --env.development --config ./build/webpack.base.js",
"bulid":"webpack --env.production --config ./build/webpack.base.js",
"dll":"webpack --config webpack.dll.js"
},
/*
可以通过--config 指定配置的文件是哪一个①默认引用base传入模式,②分别引入dev,prod,在特定地方base
{
env: { development: true },
config: './build/webpack.base.js',
}
webpack-dev-server是在内存中打包的,不会产生实体文件
*/
"sideEffects":[
"**/*.css"
],
//移除副作用(引入变量未使用,css后缀的不删除)
build/webpack.base.js文件
// webpack是基于nodejs,语法commonjs规范
//一般情况下,我们分成三个模式 一个是开发模式,一个是生产模式,还有一个基本配置模式
const dev = require('./webpack.dev');
const prod = require('./webpack.prod');
const path = require('path');
const merge = require('webpack-merge');//合并配置
const HtmlWebpackPlugin = require('webpack-html-plugin');//将html文件打包[在src下建public/index.html文件]
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const glob = require('glob');//主要功能就是查找匹配的文件
let paths = glob.sync("./src/**/*",{nodir:true});//src下任意文件夹下任意文件,nodir不找文件
//主要的作用删除无意义的css,只能配合mini-css-extract-plugin使用
const PurgeCssWebpackPlugin = require('purgecss-webpack-plugin');
const AddCdnPlugin = require('add-asset-html-cdn-webpack-plugin');
const DllReferencePlugin = require('webpack').DllReferencePlugin;
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const {BundleAnalyzerPlugin} =require('webpack-bundle-analyzer');//图像化大小查看
const smw = require('speed-measure-webpack-plugin');//费时分析
//用 smw.wrap({})把base包起来
module.exports = (env) =>{ //env是环境变量 {development:true}
let isDev = env.development;
const base = {
entry:{ //多入口
"a":"src/a.js",
"b":"src/b.js"
},
optimization:{
splitChunks:{
}
}
//入口,出口
//entry:path.resolve(__dirname,'../src/index.js'),//写路径都采用绝对路径(减少可能的修改)
output:{
fliename:'[name].js', //多出口
//filename:'bundle.js',//同步打包的名字
chunkFilename:'[name].min.js',//异步打包的名字
path:path.resolve(__dirname,'../dist') //出口必须是绝对路径
},
externals:{ // 外部资源文件
'jquery':'$', //不去打包代码中的jquery
},
module:{
//转化什么文件,用什么去转,使用哪些loader
//loader 写法 [] {} ''
//解析css的时候,不能渲染dom了
//css可以并行和js一同加载 mini-css-extract-plugin
rules:[
/*
{
test: /\.(j|t)sx?$/,
loader: "ts-loader",
exclude:/node_modules/
},
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
},
*/
{
test:/\.vue$/,
use:'vue-loader'
/*
vue 使用 typescript
需要使用垫片,即增加vue-shims.d.ts文件
declare module "*.vue"{
import Vue from 'vue';
export default Vue;
}
*/
},
{ //解析js文件,babel-loader默认会调用@babel/core,@babel-core会调用.babelrc文件
test:/\.js$/,
use:'babel-loader'
/*参数太多不方便配置,可以增加.babelrc文件,默认调用
module.exports ={
"presets":[ //从下到上执行
"@babel/preset-env",{
//使用的api会自动转化,并且是按需加载
"usageBuitIns":"usage",
//和babel-polyfill 一样
"corejs":2
},
"@babel/preset-react",
"@babel/preset-typescript",{
"allExtentions":true //匹配所有的.vue文件
}
],
"plugins":[
["@babel/plugin-proposal-decorators",{"legacy":true}],//保存装饰器语法 ["@babel/plugin-proposal-class-properties",{"loose":true}],//宽松模式this.a=a;才可以使用装饰器;严格模式使用defineProperty,不能使用装饰器
["@babel/plugin-transform-runtime"] //整合重复的代码,例如classCallback
]
}
*/
},
{
test:/\.css$/,
use:[ //生产环境再抽离 link
isDev?'style-loader':MiniCssExtractPlugin.loader,
{
loader:'css-loader?modules', //启用css modules 即styles.aa格式
options:{ //给loader传递参数
importLoaders:2 //如果css文件引入了其他文件@import
}
},'postcss-loader','sass-loader'] //postcss-loader对css进行处理
/*
需要增加文件 postcss.config.js
module.exports = {
plugins:[require('autoprefixer')] //自动添加前缀
}
需要增加文件 .browserslistrc
cover 95%
*/
},
{ //匹配到scss结尾的使用sass-loader 来调用node-sass处理sass文件
test:/\.scss$/,
use:['style-loader','css-loader','sass-loader']
},
{ //图标的转化
test:/\.(woff|ttf|eot|svg)$/,
use:'file-loader'
},
{ //图片的转化
test:/\.(jpe?g|png|gif)$/,
use:[
{
loader:'file-loader',
},
!isDev&&{ //可以在使用file-loader之前,对图片进行降清晰度压缩
loader:'img-webpack-loader',
options:{
//...
}
},
{
loader:'url-loader',
//如果大于10k,会使用file-loader
options:{
name:"image/[contentHash].[ext]",
limit:10*1024
}
}//'file-loader' //file-laoder 默认的功能是拷贝的作用
//比较小的图片可以转化成base64比以前大,好处是不用发送http请求
].filter(Boolean)
}
]
},
plugins:[
!isDev&&new MiniCssExtractPlugin({ //如果是开发模式,就不要使用抽离插件
filename:'css/main.css'
}),
new VueLoaderPlugin(),
/*
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/index.html'),
filename:'index.html',
minify:!isDev && { //在开发模式压缩index.html
removeAttributeQuotes:true,
collapseWhitespace:true
}
}),
*/
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/index.html'),
filename:'index.html',
chunks:['a']
}),
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/login.html'),
filename:'login.html',
chunksSortMode:'manual',//手动按照我的顺序排序
chunks:['b','a'] //打包的顺序,按照自己的排序
}),
new PurgeCssWebpackPlugin({
paths
}),
new DllReferencePlugin({
manifest:path.resolve(__dirname,'dll/manifest.json')
}),
//将dll加到html中
new AddAssetHtmlPlugin({
filepath:path.resolve(__dirname,'./dll/react.dll.js')
}),
!isDev&&new BundleAnalyzerPlugin(),
//当前这个dll.js没有在页面引用
//添加cdn的插件
//分割代码
new AddCdnPlugin(true,{ //第一个参数,boolean值,是否开启工作
'jquery':'https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js'
})
].filter(Boolean)
}
//函数返回配置文件,没返回采用默认配置
if(isDev){
return merge(base,dev);
}else{
return merge(base,prod);
}
}
build/webpack.dev.js文件
module.exports = {
mode:'development',//当前是开发模式(等同于package.json的 "dev":"webpack --mode development")
devServer:{ //开发服务的配置
port:3000,
compress:true,//gzip 可以提升返回页面的速度
contentBase:path.resolve(__dirname,'../dist');//webpack启动服务会在dist目录下
}
}
build/webpack.prod.js文件
const {CleanWebpackPlugin} = require('clean-webpack-plugin');//清除打包的文件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-wabpack-plugin');
const TerserWebpackPlugin= require('terser-webpack-plugin');
module.exports = {
mode:'production',//当前是生产模式
optimization:{ //优化项 (生产环境的css没办法自动压缩)
minimizer:[ //可以放置压缩方案
new OptimizeCssAssetsPlugin(),//用了这个 js也得手动压缩
new TerserWebpackPlugin() //压缩js
]
},
plugins:[
new CleanWebpackPlugin(),//在打包之前清空dist目录下文件,可以传参选择清空某些文件
]
}
webpack.dll.js
const path = require('path');
const DLLPlugin = require('webpack');
//需要产生一个缓存列表
module.exports={
mode:'development',
entry:['react','react-dom'], //第三方模块的react,react-dom打包
output:{
library:'react', //打包后接收只执行函数的名字叫calc
//libraryTarget:'commonjs2',默认用var 模式 (commonjs,commonjs2 )
filename:'react.dll.js',
path:path.resolve(__dirname,'dll')
},
plugins:[
new DLLPlugin({
name:'react',
path:path.resolve(__dirname,'dll/manifest.json')
}),
]
}
//目前是为了将calc打包成node可以使用的模块
note.md
css-loader 会解析css语法,style-loader会将解析的css变成style标签,插入到页面中
loader的执行顺序,默认是从下到上执行,从右到左执行
预处理器 .scss node-sass sass-loader
.less less less-loader
.stylus stylus styles-loader
默认会调用@babel/core 转化代码,转化的时候需要用@babel/preset-env转化成es5
@babel/core @babel/preset-env babel-loader
webpack优化
优化css,删除无用css
purgecss-webpack-plugin glob
降低图片分辨率,需要和file-loader一起用
img-webpack-loader
引用外部cdn文件
externals:{ // 外部资源文件
'jquery':'$', //不去打包代码中的jquery
},
添加cdn的插件
new AddCdnPlugin(true,{ //第一个参数,boolean值,是否开启工作
'jquery':'https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js'
})
tree-shaking 默认只支持es6 modules语法(静态导入),只在生产环境下有用
"sideEffects":[
"**/*.css"
],
//移除副作用(引入变量未使用,css后缀的不删除)
每个模块都是一个函数,会导致内存过大
scope hoisting
dllPlugin动态链接库(一般用到开发环境上)
react+react-dom先打包好,放在那
本地使用了import react语法,需要先去manifest.json查找(基于Dllreferenceplugin),找到后会加载对应的库的名字,可能会引用某个模块,会去dll.js文件中查找
dll功能在开发之前,就先抽离好,打好包,以后就不用打包了
动态加载文件
动态导入,类比路由的懒加载,import语法
会使用jsonp动态加载calc文件
import可以实现代码分割
button.addEventListen('click',function(){
import('/* webpackChunkName:'video' */' './calc').then(data=>console.log(data.add(1,2)))
})
实现多入口
index.html需要a.js ;login.html需要b.js
BundleAnalyzerPlugin
抽离第三方模块
1)不和业务逻辑放在一起
2)增加缓存 304
optimization