06_webpack的Plugin


什么是plugin

官方解释:

插件 是 webpack 的 支柱 功能。Webpack 自身也是构建于你在 webpack 配置中用到的 相同的插件系统 之上!

插件目的在于解决 loader 无法实现的其他事。Webpack 提供很多开箱即用的 插件。

Loader是用于特定的模块类型进行转换;

Plugin可以用于执行更加广泛的任务,比如打包优化,资源管理,环境变量注入等;

CleanWebpackPlugin

像我们之前运行npm run build的时候,我们的build文件生成的东西并不会清空掉,一直保留着我们之前打包过的东西
这样我们还需要手动清理,我们可以通过一个插件,帮助我们解决这个问题

安装
npm i clean-webpack-plugin

配置

//导入插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin') //在module.export中定义plugins属性,然后new一个对象 plugins: [ new CleanWebpackPlugin() ]

HtmlWebpackPlugin

在之前我们都是手动的创建index.html并且手动的去引入bundle.js

总之我们在之前对html文件的处理是不好的

我们希望在打包之后的build文件夹中有这么一个html文件并且帮我们自动引入bundle.js文件

这个时候我们可以使用HtmlWebpackPlugin插件

安装

npm i html-webpack-plugin

//1.引入
const HtmlWebpackPlugin = require('html-webpack-plugin')

//2.在module.exports配置
plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin()
  ]

那么在运行 npm run build的时候build文件夹下就会自动生成一个index.html文件,并且帮我们把bundle.js文件进行了引入
它是怎么生成的呢?通过ejs模板来进行生成的,node_modules/html-webpack-plugin/default_index.ejs

DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title><%= htmlWebpackPlugin.options.title %>title>
  head>
  <body>
  body>
html>

我们可以修改它的title

plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({ title: 'webpack' })
  ]

在vue中我们需要在body中创建一个 id为app的div,这个时候模板不会帮我们自动生成,那么怎么办呢?

我们可以自定义模板引擎

在项目目录中创建public目录,下面新建一个index.html,这里我们把vue默认的public文件拿过来

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>
    
  body>
html>

然后在配置文件中进行配置

plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: 'coderwhy',
      template: './public/index.html'
    })
  ]

但是这样子运行还是报错,因为我们自定义的模板引擎里面,有引用一个icon图标



它不是像<%= htmlWebpackPlugin.options.title %> 这样取一个变量,而是用的全局的
而我们全局中并没有这么一个BASE_URL

那么我们怎么解决这个问题?
一:删除掉 这段代码
二:在webpack定义一个全局BASE_URL常量进行赋值
怎么在全局定义常量?这就要用到DefinePlugin

DefinePlugin

DefinePlugin允许在编译时创建配置的全局常量,是一个webpack内置的插件(不需要单独安装)

也可以区别开发模式和生产模式

那么怎么使用呢?

const { DefinePlugin } = require('webpack')

  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: 'coderwhy',
      template: './public/index.html'
    }),
    new DefinePlugin({
       // 如果这里设置的是BASE_URL='./' 因为webpack在取值的时候相当于 BASE_ULR=./ 这样子的语法是有问题的,所以我们还要在外层包裹一个""
    //因为favicon.ico打包是打包在build文件夹下面的index.html也是,所以我们的路径是./
BASE_URL: "'./'" }) ]

我们项目中的icos是在public和index.html同级的,那么怎么把他打包到build文件夹中去呢?
我们可以去使用另外一个插件

CopyWebpackPlugin

安装
npm i copy-webpack-plugin

他是有非常多参数的 webpack 中文文档 (docschina.org)

配置使用

//1.引入
const CopyWebpackPlugin = require('copy-webpack-plugin')

//2.使用
  plugins: [
    new CopyWebpackPlugin({
      //匹配到哪些东西复制到哪去
      patterns: [
        {
          from: 'public',
          // to是可以省略的,他是会根据output查找路径的
          // to:"build"

          //那个文件是需要忽略的
          globOptions: {
            ignore: [
              //不这样写是会有问题的
              "**/index.html"
            ]
          }
        }
      ]
    })
  ]