webpack学习笔记

简介

webpack可以做的事

代码转换
文件优化
代码分割
模块合并
自动刷新
代码校验
自动发布

面试常见考点

webpack常见配置

webpack高级配置

ast抽象语法树

webpack中的Tapable

掌握webpack流程,手写webpack

手写webpack中常见的loader

手写webpack中常见的plugin

webpack基础配置
起步

创建src—>index.js

npx webpack
基础配置

//webpack是node写出来的,所以需要node的写法

let path = require(‘path’) //核心模块

module.exports = {
mode: ‘development’, //默认两种:production development
entry: ‘./src/index.js’, //入口
output: { //出口
filename: ‘bundle.js’, //打包后的文件名
path: path.resolve(__dirname, ‘dist’), //resolve把相对路径解析成绝对路径,__dirname意思是在当前目录建立一个,路径必须是一个绝对路径
}
}

script脚本

手动配置:npx webpack –config webpack.config.js

脚本配置:

“scripts”: {
“build”: “webpack”
}

//npm run build
传参npx webpack — –config webpack.config.js

Html插件
npx webpack-dev-server

开发服务,内部通过express实现这种服务
并不真实打包文件,只是在内存中生成

htmlWebpackPlugin
将打包后的js文件插入html文件,并放到build目录下
let htmlWebpackPlugin = require(‘html-webpack-plugin’)

module.exports = {
devServer: { //开发服务器的配置
port: 3000, //设置端口号
progress: true, //进度条
contentBase: ‘/.build’, //指定静态目录
compress: true
},
output: {
filename: ‘bundle.[hash:8].js’, //文件名
path: path.resolve(__dirname, ‘dist’),
},
plugins: [ //数组 放着所有的webpack插件
new htmlWebpackPlugin({
template: ‘./src/index.html’, //模板
filename: ‘index.html’, //打包后的文件名
minify: { //打包后的html也压缩
removeAttributeQuotes: true, //删除属性的双引号
collapseWhitespace: true, //折叠空行
},
hash: true //html文件加上哈希戳
})
]
}

css配置

loader:Webpack本身只能处理 JavaScript 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。Loader 可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果

css配置

css-loader 解析@import这种语法

style-loader把css插入到head的标签中

loader的特点:希望单一

loader的用法:字符串只用一个loader,多个loader需要[]

loader的顺序:默认是从右向左执行       从下往上

优先级
{
loader: ‘style-loader’,
options: {
insertAt: ‘top’ //确保优先级
}
}
处理less、sass、stylus

yarn add less less-loader
yarn add node-sass sass-loader
yarn add stylus stylus-loader

module.exports = {
module: { //模块
rules: [ //规则
//loader的特点:希望单一
//{ test: /\.css$/, use: [‘style-loader’, ‘css-loader’] } //第一种:写法
//loader还可以写成对象方式
{
//处理less文件
test: /\.css$/,
use: [{
loader: ‘style-loader’,
options: {
insertAt: ‘top’ //确保优先级
}
},
‘css-loader’, //@import 解析路径
‘less-loader’ //把less —->css
]
}
]
}
}
抽离CSS的插件

默认打包后只能插入<style>标签内,我们希望抽离成<link>形式
通过 mini-css-extract-plugin这个插件
yarn add mini-css-extract-plugin -D
插件都是类,插件的使用顺序没有先后

let MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

//配置plugin
plugins: [
new MiniCssExtractPlugin({
filename: ‘main.css’,
})
],

//配置module
module: {
rules: [{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, ‘css-loader’]
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, ‘css-loader’, ‘less-loader’]
}
]
}
自动添加前缀

autoprefixer
前提要用postcss-loader

yarn add postcss-loader autoprefixer

//配置module
//先处理post-css再处理css
module: {
rules: [{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, ‘css-loader’,’postcss-loader’] //加上post-css
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, ‘css-loader’, ‘postcss-loader’, ‘less-loader’]
}
]
}
//创建postcss.config.js文件并配置

module.exports = {
plugins: [require(‘autoprefixer’)]
}
压缩css(同时保证js的压缩)

通过optimize-css-assets-webpack-plugin

yarn add optmize – css – assets – webpack – plugin – D
uglifyjs-webpack-plugin

let path = require(‘path’)
let htmlWebpackPlugin = require(‘html-webpack-plugin’)
let MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
let OptimizeCss = require(‘optimize-css-assets-webpack-plugin’)
let UglifyJsPlugin = require(‘uglifyjs-webpakc-plugin’)

module.exports = {
Optimization: { //***优化项,用了这个插件之后就必须用一下Uglifyjs压缩js
minimizer: [
new UglifyJsPlugin({
cache: true, //是否用缓存
parallel: true, //是否并行打包
sourceMap: true
}),
new OptimizeCss()
]
},
devServer: {
port: 3000,
progress: true,
contentBase: ‘/.build’
},
mode: ‘development’,
entry: ‘./src/index.js’,
output: {
filename: ‘bundle.[hash:8].js’,
path: path.resolve(__dirname, ‘dist’),
},
plugins: [
new htmlWebpackPlugin({
template: ‘./src/index.html’,
filename: ‘index.html’,
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
},
hash: true
}),
new MiniCssExtractPlugin({
filename: ‘main.css’
})
],
module: {
rules: [
//{ test: /\.css$/, use: [‘style-loader’, ‘css-loader’] }
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, //***创建link标签,引用
‘css-loader’,
‘less-loader’,
‘postcss-loader’

]
}
]
}
}

JS配置
转化es6语法
babel

yarn add babel-loader @babel/core @babel/preset-env -D
配置module

module: {
rules: [{
test: /\.js$/,
use: {
loader: ‘babel-loader’,
options: { //用babel-loader es6—->es5
presets: [
‘@babel/preset-env’
]
}
}
}
]
}

配置提案里支持的语法
class A{
a = 1;
}
yarn add @babel/plugin-proposal-class-properties -D
{
test: /\.js$/,
use: {
loader: ‘babel-loader’,
options: {
presets: [
‘@babel/preset-env’
],
plugins: [
‘@babel/plugin-proposal-class-properties’
]
}
}
}
支持装饰器语法
function log(target) {
console.log(target, ’23’)
}

log(A)
yarn add @babel/plugin-proposal-decorators -D
配置module

module: {
rules: [{
test: /\.js$/,
use: {
loader: ‘babel-loader’,
options: { //用babel-loader es6—->es5
presets: [
‘@babel/preset-env’
],
plugins: [
[‘@babel/plugin-proposal-class-properties’],
[‘@babel/plugin-proposal-decorators’,{“legacy”:true}],
[‘@babel/plugin-transform-runtime’]
]
}
}
}
]
}
处理JS语法及校验
function *gen(params){
yield 1;
}
console.log(gen().next()); //内置API

// Uncaught ReferenceError: regeneratorRuntime is not defined

babel-runtime

yarn add @babel/plugin-transform-runtime -D
yarn add @babel/runtime

module: {
rules: [{
test: /\.js$/,
use: {
loader: ‘babel-loader’,
options: { //用babel-loader es6—->es5
presets: [
‘@babel/preset-env’
],
plugins: [
[‘@babel/plugin-proposal-class-properties’], [‘@babel/plugin-proposal-decorators’,{“legacy”:true}],
[‘@babel/plugin-transform-runtime’]
]
}
},
include:path.resolve(__dirname,’src’), //包括查找范围
exclude:/node_module/ //排除查找范围
}
]
}
@babel/polyfill
‘aaa’.include(‘a’) //ES7语法

//实例上的方法默认都不会解析
yarn add @babel/polyfill
//a.js
require(‘@babel/polyfill’)
‘aaa’.include(‘a’)
eslint
yarn add eslint eslint-loader
module: {
rules: [ //loader默认从右向左执行 从下到上,写的太多容易乱,写到一起删除不方便
{
test:\.js$/,
use:{
loader:’eslint-loader’,
options:{
enforce:’pre’ //previous -> normal-> post 顺序执行
}
}
}
/*…*/
]
}

选择好配置,下载.eslintrc.json到configuration

全局变量引入问题

第三方模块引用
yarn add jquery

import $ form ‘jqurey’
console.log($)
console.log(window.$) //undefined,并不会挂载到window上
如何将变量暴露给window?

expose-loader (内联loader)
yarn add expose-loader
import $ from ‘expose-loader?$!jquery’ //将jquery作为$暴露给全局
也可以在webpack.config.js中配
module: {
rules: [{
test: require.resolve(‘jquery’),
use: ‘expose-loader?$!jquery’
}
]
}
在每个模块中注入$对象
//webpack.config.js
let Webpack = require(‘webpack’)
new Webpack.ProvidePlugin({
//再每个模块中都注入$符
jqurey: ‘$’
})
//index.js
console.log($) //只是在每个模块中都注入一个`$`
//此时window.$ //undefined

cdn外部路径引入
<script src=”https://cdn.bootcss.com/jquery/3.3.1/core.js”></script>
//如果此时js也引入jquery会导致重复
import $ form jquery
externals: {
jquery: ‘jQuery’ //告诉webpack从外部引入,并不需要打包,忽略
},
总结

expose-loader:暴露到window上

providePlugin:给每个提供一个
引入不打包

loader类型

pre             前面执行的loader

normal        普通的loader

liader        内联loader

post            后置loader

图片处理
图片引入方式
在js中创建图片来引入
let image = new Image()
image.src = ‘./logo.png’
document.body.appendChild(image) //打包完,其实就是一个普通的字符串,并没有真正的引入图片
file-loader

yarn add file-loader
默认在内部生成图片,到build目录下,并且把生成的路径的名字返回回来

//webpack.config.js

module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: ‘file-loader’
}
]
}
//index.js

import logo from ‘./logo.png’ //把图片引入,生成一个哈希戳的logo,返回的结果是一个新的图片

console.log(logo)

let image = new Image();
image.src = logo;
document.body.appendChild(image)

在css中引入background(‘url’)

<img src=”” alt=””>

打包文件分类
打包多页应用
配置source-map

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理