webpack配置之Loader与Plugin

211 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

一、查看vue-cli中默认的webpack配置

vue inspect --mode=development >  webpack.development.js
vue inspect --mode=production >  webpack.production.js

默认inspect导出文件的mode为development

这里也可以选择性的查看配置或规则

可以在vue.config.js文件中对配置做更改

chainWebpack

chainWebpack 配置项允许我们更细粒度的控制 webpack 的内部配置,可以让我们能够使用链式操作来修改配置。

  chainWebpack: config => {
    // 移除 prefetch 插件
    config.plugins.delete('prefetch')
    config.module
      .rule('file')
      .test(/\.(zip|xls|pdf|doc|docx)(\?.*)?$/)
      .use('file-loader')
      .loader('url-loader')
      .options({
        limit: 1,
        name: 'file/[name].[ext]'
      })
      .end()

configureWebpack

除了上述使用 chainWebpack 来改变 webpack 内部配置外,我们还可以使用 configureWebpack 来进行修改,两者的不同点在于 chainWebpack 是链式修改,而 configureWebpack 更倾向于整体替换和修改。

configureWebpack 可以直接是一个对象,也可以是一个函数,如果是对象它会直接使用 webpack-merge 对其进行合并处理,如果是函数,你可以直接使用其 config 参数来修改 webpack 中的配置,或者返回一个对象来进行 merge 处理。

  configureWebpack: config => {
    // 开发环境不需要gzip
    if (process.env.NODE_ENV === 'production') {
      config.plugins.push(
        new CompressionWebpackPlugin({
          // 正在匹配需要压缩的文件后缀
          test: /\.(js|css|svg|woff|ttf|json|html)$/,
          // 大于10kb的会压缩
          threshold: 10240
          // 其余配置查看compression-webpack-plugin
          // deleteOriginalAssets: true // 删除原文件
          // minRatio:0.8, // 只有压缩率小于这个值的资源才会被处理
          // filename: '[path].gz[query]',
        })
      )
    }
  },

二、Loader

loader的本质是一个函数,可以把它当作一个转换器,一种处理多种文件格式的机制。使用不同的loader来解析不同类型的文件

//用来获取options中的参数
const { getOptions } = require('loader-utils')
//用来验证接受到的参数是否符合规范
const { validate } = require('schema-utils')
//配置参数应具备的格式
const schema = require('./schema')

//同步loader的两种写法1/* 函数接收三个参数,接受的文件,文件的映射信息,文件的元信息 */
module.exports = function (content, map, meta) {
  const options = getOptions(this)
  console.log('test', options)
  //校验options是否合法
  validate(schema, options, {
    name:'loader'
  })
  return content 
}
(2module.exports = function (content, map, meta) {
  console.log('test')
  this.callback(null,content,map,meta)
}

异步loader写法
module.exports = function (content, map, meta) {
  console.log('test')
  const callback = this.async()
  
  setTimeout(() => {
    callback(null,content)
  },1000)
}

// .pitch 执行顺序 会按次序先执行
module.exports.pitch = function () {
    console.log('pre')
}

三、Plugin

plugin的本质是一个类,在不同钩子函数阶段执行,在特定的时机对资源做处理

//compiler
class Plugin{
  apply(compiler) {
    compiler.hooks.emit.tap('Plugin', (compilation) => {
      console.log('emit')
    })
    compiler.hooks.emit.tapAsync('Plugin', (compilation,cb) => {
      setTimeout(() => {
        console.log('emit tapasync')
        cb()
      }, 666);
    }) 
    compiler.hooks.emit.tapPromise('Plugin', (compilation) => {
      return new Promise((resolve) => {
        setTimeout(() => {
        console.log('emit tapPromise')
          resolve()
      }, 666);
      })
      }) 
    compiler.hooks.afterEmit.tap('Plugin', (compilation) => {
      console.log('afterEmit')
      }) 
    }
}
module.exports= Plugin

四、常用的loader和plugin

image.png