webpack5学习笔记-1

webpack功能
打包:将不同类型资源按模块处理进行打包
静态:打包最后产出静态资源
模块:webpack支持不同规范的模块化开发

一、Loader

起到转换的作用,把当前代码转成webpack能识别处理的模块
webpack5中,在cli里面写loader的方式已经被废弃

1、CSS-Loader和style-loader

npm i css-loader style-loader -D

行内loader,单独使用不会报错,但是不会起作用,还要加上style-loader

import 'css-loader!../css/login.css'

function login() {
  const oH2 = document.createElement('h2')
  oH2.innerHTML = '拉勾教育前端'
  oH2.className = 'title'
  return oH2
}

document.body.appendChild(login())

配置文件

const path = require('path')

module.exports = {
  ...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
}

如果有less或者sass,则新增一个less-loader处理

{
  test: /\.less$/,
  use: ['style-loader', 'css-loader', 'less-loader']
}

2、browserslistrc和postcss

2-1 .browserslistrc
> 1% 
last 2 version
not dead

使用postcss处理CSS兼容之前需要进行配置
www.caniuse.com 浏览器兼容性查询网站,node_modules里browserslist包会去这个网站匹配

1%,兼容处理市面上占有率大于1%的浏览器
deafault,0.5%
dead 24个月没更新,没支持
last 2 version 最新的2个版本
也可以直接在package.json里配置browserslist属性

2-2 postcss

利用js来转换样式做兼容的工具,在不兼容的css属性和值前面加上前缀
如果是使用postcss-cli命令行手动的话,就是根据之前写的browserslistrc配置信息,然后使用autoprefixer来进行css修改
npm i postcss-cli autoprefixer -D
npx postcss --use autoprefixer -o rest.css ./src/css/test.css

webpack里则可以通过loader
npm i postcss-loader -D

{
  test: /\.css$/,
  use: [
    'style-loader',
    'css-loader',
    'postcss-loader'
  ]
}

npm i postcss-preset-env -D
color的rgba写法或者一些新特性,部分浏览器无法兼容,使用postcss-preset-env这个预设的插件集合来进行处理,这个集合里已经有之前使用的autoprefixer

{
  test: /\.css$/,
  use: [
    'style-loader',
    'css-loader',
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: ['postcss-preset-env']
        }
      }
    }
  ]
}
2-3 复用配置属性

但是,此时如果有less或者sass的时候,又需要把前面写的重新写一份,这样代码就冗余,webpack提供了一种复用的额外配置方式
在项目根目录下创建postcss.config.js

module.exports = {
  plugins: [
    // require('postcss-preset-env')
    require('autoprefixer')
  ]
}

之后,就可以直接写postcss,不用多写插件配置

{
  test: /\.css$/,
  use: [
    'style-loader',
    'css-loader',
    'postcss-loader'
  ]
},
{
  test: /\.less$/,
  use: [
    'style-loader',
    'css-loader',
    'postcss-loader',
    'less-loader'
  ]
}
2-4 导入样式处理

之前我们处理的样式兼容,如果是通过@import进来的postcss无法处理

@import './test.css';
.title {
  color: #12345678;
}

导入之后,当前css文件交给postcss处理,基于当前的筛选条件,postcss-loader发现不需要处理,交给了css-loader,而css-loader可以处理@import、@media和url等
这个时候它获取到了test.css,但是无法返回给postcss进行处理,只能进行下一步
webpack考虑到了这个情况,提供了importLoaders属性,值为数字,代表遇到了这种情况,往前找第几个loader

{
  test: /\.css$/,
  use: [
    'style-loader',
    {
      loader: 'css-loader',
      options: {
        importLoaders: 1
      }
    },
    'postcss-loader'
  ]
}

3、图片处理

3-1 file-loader

打包图片文件,返回webpack能识别的格式
把要处理的图片资源,用hash改名后拷贝到指定目录,默认是dist目录,然后在使用的地方返回路径
npm i file-loader -D

3-1-1 img src
{
  test: /\.(png|svg|gif|jpe?g)$/,
  use: ['file-loader']
}

webpack5中,file-loader返回的资源变成了一个对象,其中default属性才是真正需要的资源,要改写法

function packImg() {
  const oEle = document.createElement('div')
  const oImg = document.createElement('img') 
  oImg.width = 600
  oImg.src = require('../img/01.wb.png').default
  oEle.appendChild(oImg)
  return oEle
}

document.body.appendChild(packImg())

如果不想这样写,webpack需要改一下配置,esModule,含义是,是否将导出的内容转为esmodule

{
  test: /\.(png|svg|gif|jpe?g)$/,
   use: [
     {
       loader: 'file-loader',
       options: {
         esModule: false // 不转为 esModule
       }
     }
   ]
}
function packImg() {
  const oEle = document.createElement('div')
  const oImg = document.createElement('img') 
  oImg.width = 600
  oImg.src = require('../img/01.wb.png')
  oEle.appendChild(oImg)
  return oEle
}

document.body.appendChild(packImg())

还有一种写法,采用esmodule的导入方法,webpack配置改回之前的写法

import oImgSrc from '../img/01.wb.png'

function packImg() {
  const oEle = document.createElement('div')
  const oImg = document.createElement('img')
  oImg.width = 600
  oImg.src = oImgSrc
  oEle.appendChild(oImg)
  return oEle
}

document.body.appendChild(packImg())
{
  test: /\.(png|svg|gif|jpe?g)$/,
  use: ['file-loader']
}
3-1-2 background src
.bgBox {
  width: 240px;
  height: 310px;
  border: 1px solid #000;
  background-image: url('../img/02.react.png');
}
import '../css/img.css'


function packImg() {
  const oEle = document.createElement('div')
  const oBgImg = document.createElement('div')
  oBgImg.className = 'bgBox'
  oEle.appendChild(oBgImg)

  return oEle
}

document.body.appendChild(packImg())

css文件中使用了url的时候,css-loader在解析时会默认转为对象,所以需要修改配置

{
  test: /\.css$/,
  use: [
    'style-loader',
    {
      loader: 'css-loader',
      options: {
        importLoaders: 1,
        esModule: false
      }
    },
    'postcss-loader'
  ]
},
{
  test: /\.(png|svg|gif|jpe?g)$/,
  use: ['file-loader']
}
3-1-3 配置图片名字和输出的路径

扩展名
● [ext]: 扩展名
● [name]: 文件名
● [hash]: 根据文件内容和MD4算法生成的128位hash值
● [contentHash]:file-loader里和hash一样
● [hash:length]:固定长度的hash
● [path]:不常用

输出的路径:dist目录下的文件夹名字,可以写在outputPath属性,也可以直接在名字前面加路径

{
  test: /\.(png|svg|gif|jpe?g)$/,
  use: [
    {
      loader: 'file-loader',
      options: {
        name: 'img/[name].[hash:6].[ext]'//outputPath: 'img'
      }
    }
  ]
}
3-2 url-loader

npm i url-loader -D
把要打包的图片资源以base64 URI的方式加载到代码里
优点:只需要请求一次,减少请求次数
缺点:当前图片如果过大,一次性请求的数据量过大,请求速度可能达不到业务要求
所以,需要限制使用url-loader时的图片大小,使用limit属性进行限制,超过限制的url-loader会自动去调用已经安装的file-loader

{
  test: /\.(png|svg|gif|jpe?g)$/,
  use: [
    {
      loader: 'url-loader',
      options: {
        name: 'img/[name].[hash:6].[ext]',
        limit: 25 * 1024
      }
    }
  ]
}
3-3 asset

webpack5中新增的处理图片和字体的资源类型模块,不需要再使用loader

图片

asset module type可以直接写type的值为下面3个,代表之前的loader
● asset/resource -->file-loader( 输出路径 )
● asset/inline —>url-loader(所有 data uri)
● asset/source —>raw-loader
● asset (parser )

output: {
  filename: 'main.js',
  path: path.resolve(__dirname, 'dist'),
  assetModuleFilename: "img/[name].[hash:4][ext]"
}
....
{
  test: /\.(png|svg|gif|jpe?g)$/,
  type: 'asset/resource',
}

上面这样的话,名称修改就变成全局的了,不太合适,所以要改到图片处理部分写generator

{
  test: /\.(png|svg|gif|jpe?g)$/,
  type: 'asset',
  generator: {
    filename: "img/[name].[hash:4][ext]"
  },
  parser: {
    dataUrlCondition: {
      maxSize: 30 * 1024
    }
  }
}
字体
{
  test: /\.(ttf|woff2?)$/,
  type: 'asset/resource',
  generator: {
    filename: 'font/[name].[hash:3][ext]'
  }
}

二、plugin插件

loader对特定的文件类型进行转换,在读取某一个特定类型的资源时开始工作
plugin可以做更多事情,在打包的生命周期中任一钩子来操作

clean-webpack-plugin

和之前的一样用,npm i clean-webpack-plugin -D安装,然后导入使用

const {CleanWebpackPlugin} = require('clean-webpack-plugin')
plugins:[new CleanWebpackPlugin()]

html-webpack-plugin

npm i html-webpack-plugin -D
在dist目录下创建html,并且自动引入JS文件,DefinePlugin是webpack内置,用来使用公共变量的插件

const { DefinePlugin } = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

plugins: [
  new CleanWebpackPlugin(),
  new HtmlWebpackPlugin({
    title: 'html-webpack-plugin',
    template: './public/index.html'
  }),
  new DefinePlugin({
    BASE_URL: '"./"'
  })
]

index.html的模板

<!DOCTYPE html>
<html lang="">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">

  <link rel="icon" href="<%= BASE_URL %>favicon.ico">

  <title>
    <%= htmlWebpackPlugin.options.title %>
  </title>
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
        Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>

</html>

copy-webpack-plugin

npm i copy-webpack-plugin -D
将静态资源拷贝到dist目录下

const CopyWebpackPlugin = require('copy-webpack-plugin')
const { DefinePlugin } = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

plugins: [
  new CleanWebpackPlugin(),
  new HtmlWebpackPlugin({
    title: 'copyWebpackPlugin',
    template: './public/index.html'
  }),
  new DefinePlugin({
    BASE_URL: '"./"'
  }),
  new CopyWebpackPlugin({
    patterns: [
      {
        from: 'public',
        globOptions: {
          ignore: ['**/index.html']
        }
      }
    ]
  })
]

三、babel

babel是一个JS编译器,用来转换最新的JS语法,把ES6, ES7等语法转化成ES5语法,从而能够在大部分浏览器中运行
编译过程:
1.parse分析:第一步是babel使用babylon将原始代码转换为AST抽象语法树
2.transform转化:第二步是babel通过babel-traverse对前面的抽象语法树进行遍历修改并获得新的抽象语法树
3.generator生成代码:第三步是babel使用babel-generator将抽象语法树转换为代码
这三个操作通过babel-core合成一个对外的api供外界使用

babel-loader
npm i babel-loader @babel/core @babel/preset-env -D

{
  test: /\.js$/,
  use: ['babel-loader']
}

根目录下创建babel.config.js

module.exports = {
  presets: ['@babel/preset-env']
}

也可以直接在webpack.config.js写

{
  test: /\.js$/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env']
      }
    }
  ]
}

四、polyfill

babel默认只转化新的js句法,而不会处理新的API,所以需要polyfill来处理,它会新增对应的方法
webpack5之后要优化速度,polyfill包太大,不需要安装@babel/polyfill,自己配置
npm i core-js regenerator-runtime
注意的是,我们用的第三方包可能也用到了一些新的API,但是我们的代码没有,如果值设置的是usage不会填充进来,所以还是使用entry

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        // false: 不对当前的JS处理做 polyfill 的填充
        // usage: 依据用户源代码当中所使用到的新语法进行填充
        // entry: 依据我们当前筛选出来的浏览器决定填充什么
        useBuiltIns: 'entry',
        corejs: 3
      }
    ]
  ]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值