初探webpack--引入功能

342 阅读2分钟

关键词

常用loader使用、常用plugin使用、devServer搭建、自定义plugin

所用版本

"webpack": "^5.61.0",
"webpack-cli": "^4.9.1"

处理css文件

1. 打包css

  • css-loader

    css转化为js,打包到js文件中

  • style-loader

    将包含css内容的js代码挂载到<style>标签 下载两个loader

npm -i -D css-loader style-loader

入口文件main.js中引入css文件

import './style/base.css'

webpack.config.js中配置

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

loader执行顺序,先右后左、先下后上

2. 打包less

  • less-loader

    less语法转为普通的css语法

安装less服务和less-loader

npm -i -D less less-loader

入口文件main.js中引入css文件

import './style/base.less'

webpack.config.js中配置

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

3. 将css打包成独立文件,不放到js中

实际开发中,会将css打包到单独的css文件中,再在html文件中使用link标签引入

安装pluginmini-css-extract-plugin

npm i -D mini-css-extract-plugin

webpack.config.js中配置

使用miniCssExtractPlugin.loader替换掉之前的style-loader(将js文件中包含的css代码插入中)

const miniCssExtractPlugin = require('mini-css-extract-plugin')
​
module: {
    rules: [
      {
        test: /.css$/,
        // use: [ 'style-loader', 'css-loader' ]
        use: [ miniCssExtractPlugin.loader, 'css-loader' ]
      },
      {
        test: /.less$/,
        use: [ miniCssExtractPlugin.loader, 'css-loader', 'less-loader' ]
      }
    ]
  },

4. 给样式添加浏览器前缀

需要用到postcss-loader和它内部的plugin:autoprefixer

什么是postcss

是一个用 JavaScript 工具和插件转换 CSS 代码的工具

提到工具,那肯定会想到css预处理器:lesssass/scssstylus等等,我用过前面两个。我觉得css预处理器的作用就是弥补css的语法能力,因为css本身不支持嵌套、不支持变量,写一个简单页面可能就会写一大堆的css样式代码,可读性可维护性较差,所以就需要less这样的预处理器去让我们能像写js一样去写css,之后再用less-loader这样的转换器让我们写的less转换成浏览器可识别的css语法,正常跑起来。

postcss更强大一点,它就像是css界的webpack。它是处理css的工具平台,它下面有很多的插件,这些插件能让它预处理css和所谓的后处理css

比如使用postcss-for插件就可编译我们在css中写的for循环

@for $i from 1 to 3 {
    p:nth-of-type($i) {
      margin-left: calc( 100% / $i );
    }
}
p:nth-of-type(1) {
    margin-left: calc( 100% / 1 );
}
 
p:nth-of-type(2) {
  margin-left: calc( 100% / 2 );
}
 
p:nth-of-type(3) {
  margin-left: calc( 100% / 3 );
}

这让它有了预处理的能力,而使用autoprefixer插件则可以向编译好的css语法添加浏览器前缀去适配某些低版本浏览器

安装

npm i -D postcss-loader autoprefixer

新建postcss.config.js文件,配置插件autoprefixer

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}

package.json文件中配置兼容哪些浏览器

"browserslist": [
    "> 1%", // 兼容市场占有率 > 1%的浏览器
    "last 2 versions" // 兼容最新的两个版本
  ]

webpack.config.js中使用postcss-loader

module: {
    rules: [
      {
        test: /.css$/,
        // use: [ 'style-loader', 'css-loader' ]
        use: [ miniCssExtractPlugin.loader, 'css-loader', 'postcss-loader' ]
      },
      {
        test: /.less$/,
        use: [ miniCssExtractPlugin.loader, 'css-loader', 'postcss-loader' ,'less-loader' ]
      }
    ]
  },

处理html文件

webpack本身可识别jsjson文件,再加上loader可处理css文件,但这些文件最终都要挂载到html文件上才可实现他们的价值

安装

npm i -D html-webpack-plugin

webpack.config.js文件中配置使用

const htmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
    new miniCssExtractPlugin(),
    new htmlWebpackPlugin({
      template: './src/index.html' // 指定模板
    })
  ],

这样就可在我们指定的出口目录下生成index,html文件,并且它会引入我们之前打包好的js文件以及css文件,所以在实际开发中将这个dist文件夹下面的所有文件放到服务器上,并且以index.html文件为载体即可将网站跑起来

处理js文件

转译ES6+新语法,适配低版本浏览器

  • babel-loader

  • @babel/core

    babel插件集合,包含了很多常用插件,例如能转译箭头函数的arrow-functions插件、转移class类的classes插件

  • @babel/preset-env

    babel转换规则集合,比如ES7转化ES5有一套转换规则,ES6ES5也有一套规则,但是它只支持转译一些基本语法,一些高级语法比如promise不支持

  • @babel/polyfill

    支持转译所有语法,但是会强制转译所有,所以打包出来的文件过大

  • core-js

    按需转译用到的语法 安装

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

webpack.config.js配置

{
  test: /.m?js$/,
  exclude: /node_modules/,
  use: {
    loader: 'babel-loader',
    options: {
      presets: [
        [
          '@babel/preset-env',
          {
            useBuiltIns: 'usage', // 按需加载
            corejs: 3, // core-js版本
            targets: "defaults"
          }
        ]
      ]
    }
  }
}

devServer

开启本地node服务,方便开发调试

devServer也会去打包文件,但是它不会像build一样去生成文件,它是会把打包好的文件放在内存中去读取

而且webpack5.x版本下的devServer是默认打开热更新hot: true的,不用去额外配置

安装

npm i -D webpack-dev-server
devServer: {
  static: {
    directory: join(__dirname, 'dist'),
  },
  compress: true, // 压缩
  port: 9000
}

自定义plugin(每次打包前都删除一遍打包目录)

实现

const del = require('del')
const path = require('path')

class cleanDistPlugin {
  constructor(options = {}) {
    this.outputPath = ''
  }
  apply(compiler) {
    // 拿到webpack.config.js中的output.path
    this.outputPath = compiler.options.output.path;
    compiler.hooks.emit.tap('clean-dist-plugin', () => {
      try {
        const deleted = del.sync(['*'], {
          cwd: this.outputPath, // 待删除的目录
          dot: true // 支持匹配以.开头的目录
        })
      } catch (error) {
        throw error
      }
    })
  }
}
module.exports = cleanDistPlugin

ps:看了 clean-webpack-plugin 的源码,get了它的核心代码

使用

const myCleanPlugin = require('./plugins/clean-dist-plugin')
plugins: [
    new miniCssExtractPlugin({
      filename: 'index.css'
    }),
    new htmlWebpackPlugin({
      template: './src/index.html', // 指定模板
      filename: 'index.html'
    }),
    new myCleanPlugin()
],

require查找依赖顺序

image.png