webpack 之 loader 和 plugin 简介

webpack是一个模块打包器(module bundler),提供了一个核心,核心提供了很多开箱即用的功能,同时它可以用loader和plugin来扩展。webpack本身结构精巧,基于tapable的插件架构,扩展性强,众多的loader或者plugin让webpack显得很复杂。
webpack常用配置包括:devtool、entry、 output、module、resolve、plugins、externals等,本文主要介绍下webpack常用的loader和plugin  

一、loader

       1.1、loader的使用方式

webpack允许我们使用loader来处理文件,loader是一个导出为function的node模块。可以将匹配到的文件进行一次转换,同时loader可以链式传递。

一般loader的使用方式分为三种:
1:在配置文件webpack.config.js中配置

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

2:通过命令行参数方式

webpack --module-bind 'txt=raw-loader'

3:通过内联使用

import txt from 'raw-loader!./file.txt';

1.2、webpack常用的loader

  • 样式:style-loader、css-loader、less-loader、sass-loader等
  • 文件:raw-loader、file-loader 、url-loader等
  • 编译:babel-loader、coffee-loader 、ts-loader等
  • 校验测试:mocha-loader、jshint-loader 、eslint-loader等

比如下面配置,可以匹配.scss的文件,分别经过sass-loader、css-loader、style-loader的处理。
sass-loader转化sass为css文件,并且包一层module.exports成为一个js module。style-loader将创建一个style标签将css文件嵌入到html中。css-loader则处理其中的@import和url()。

module.exports = {
  module: {
    rules: [
        {
          test: /\.scss$/,
          use:[
              {loader:'style-loader'},
              {loader:'css-loader',options:{sourceMap:true,modules:true}},
              {loader:'sass-loader',options:{sourceMap:true}}
          ],
          exclude:/node_modules/
      }
    ]
  }
}
  • vue-loader、coffee-loader、babel-loader等可以将特定文件格式转成js模块、将其他语言转化为js语言和编译下一代js语言
  • file-loader、url-loader等可以处理资源,file-loader可以复制和放置资源位置,并可以指定文件名模板,用hash命名更好利用缓存。
  • url-loader可以将小于配置limit大小的文件转换成内敛Data Url的方式,减少请求。
  • raw-loader可以将文件以字符串的形式返回
  • imports-loader、exports-loader等可以向模块注入变量或者提供导出模块功能,常见场景是:
    1:jquery插件注入$,imports-loader?$=jquery
    2:禁用AMD,imports-loader?define=false
    等同于:var $ = require("jquery") 和 var define = false;
  • expose-loader:暴露对象为全局变量

1.3、如何写一个loader:官网介绍how to write a loader

下面是一个简单的raw-loader,它可以将文本类文件转成字符串到js文件中。其中this.cacheable、this.value等是loader的api,分别是将结果标记为可缓存和把值传递给下一个loader。

module.exports = function(content) {
  this.cacheable && this.cacheable();
  this.value = content;
  return "module.exports = " + JSON.stringify(content);
}

二、plugin

webpack的plugin比loader强大,通过钩子可以涉及整个构建流程,可以做一些在构建范围内的事情。

2.1、webpack常用的plugin

  • 官网介绍plugins
  • 第三方插件awesome-webpack
  • 首先webpack内置UglifyJsPlugin,压缩和混淆代码。
  • webpack内置CommonsChunkPlugin,提高打包效率,将第三方库和业务代码分开打包。
  • ProvidePlugin:自动加载模块,代替require和import
new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery'
  })
  • html-webpack-plugin可以根据模板自动生成html代码,并自动引用css和js文件
  • extract-text-webpack-plugin 将js文件中引用的样式单独抽离成css文件
  • DefinePlugin 编译时配置全局变量,这对开发模式和发布模式的构建允许不同的行为非常有用。
new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(true),
  VERSION: JSON.stringify("5fa3b9"),
  BROWSER_SUPPORTS_HTML5: true,
  TWO: "1+1",
  "typeof window": JSON.stringify("object")
})
  • HotModuleReplacementPlugin 热更新

    • 添加HotModuleReplacementPlugin
    • entry中添加 "webpack-dev-server/client?http://localhost:8080/",
    • entry中添加 "webpack/hot/dev-server"
    • (热更新还可以直接用webpack_dev_server --hot --inline,原理也是在entry中添加了上述代码)
  • webpack 内置的DllPluginDllReferencePlugin相互配合,前置第三方包的构建,只构建业务代码,同时能解决Externals多次引用问题。DllReferencePlugin引用DllPlugin配置生成的manifest.json文件,manifest.json包含了依赖模块和module id的映射关系

  • babili-webpack-plugin、transform-runtime 、transform-object-rest-spread
    • babili-webpack-plugin:构建在babel之上 why
    • transform-runtime :解决了babel在每个文件都插入了辅助代码,代码体积过大的问题。
    • transform-object-rest-spread:
      Transform rest properties for object destructuring assignment and spread properties for object literals
      为对象字面量添加解构赋值和spread属性
  • optimize-css-assets-webpack-plugin 不同组件中重复的css可以快速去重

  • webpack-bundle-analyzer 一个webpack的bundle文件分析工具,将bundle文件以可交互缩放的treemap的形式展示。
  • compression-webpack-plugin 生产环境可采用gzip压缩JS和CSS
  • happypack:通过多进程模型,来加速代码构建

const os = require('os');
    let HappyPack = require('happypack');
    let happyThreadPool = HappyPack.ThreadPool({size: os.cpus().length});
    exports.plugins = [
      new HappyPack({
        id: 'jsx',
        threadPool: happyThreadPool,
        loaders: [ 'babel-loader' ]
      }),

      new HappyPack({
        id: 'coffeescripts',
        threadPool: happyThreadPool,
        loaders: [ 'coffee-loader' ]
      })
    ];

    exports.module.loaders = [
      {
        test: /\.js$/,
        loaders: [ 'happypack/loader?id=jsx' ]
      },
      {
        test: /\.coffee$/,
        loaders: [ 'happypack/loader?id=coffeescripts' ]
      },
    ]

2.2、写一个webpack插件:

官网介绍:how to write a plugin

主要的步骤如下:
  • 编写一个JavaScript命名函数。
  • 在它的原型上定义一个apply方法。
  • 指定挂载的webpack事件钩子。
  • 处理webpack内部实例的特定数据。
  • 功能完成后调用webpack提供的回调。
// 一个 JavaScript 命名函数。
function MyExampleWebpackPlugin() {

};

// 在插件函数的 prototype 上定义一个 `apply` 方法。
MyExampleWebpackPlugin.prototype.apply = function(compiler) {
  // 指定一个挂载到 webpack 自身的事件钩子。
  compiler.plugin('webpacksEventHook', function(compilation /* 处理 webpack 内部实例的特定数据。*/, callback) {
    console.log("This is an example plugin!!!");

    // 功能完成后调用 webpack 提供的回调。
    callback();
  });
};

Compiler 和 Compilation

编写插件之前要理解compiler和compilation两个对象,以及webpack生命周期的各个阶段和钩子,plugin比loader强大,通过plugin你可以访问compliler和compilation过程,通过钩子拦截webpack的执行。

在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。理解它们的角色是扩展 webpack 引擎重要的第一步。 

    • compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。

    • compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。

基本插件架构

插件是由「具有 apply 方法的 prototype 对象」所实例化出来的。这个 apply 方法在安装插件时,会被 webpack compiler 调用一次。apply 方法可以接收一个 webpack compiler 对象的引用,从而可以在回调函数中访问到 compiler 对象。一个简单的插件结构如下:

function HelloWorldPlugin(options) {
  // 使用 options 设置插件实例……
}

HelloWorldPlugin.prototype.apply = function(compiler) {
  compiler.plugin('done', function() {
    console.log('Hello World!');
  });
};

module.exports = HelloWorldPlugin;

然后,要安装这个插件,只需要在你的 webpack 配置的 plugin 数组中添加一个实例:

var HelloWorldPlugin = require('hello-world');

var webpackConfig = {
  // ... 这里是其他配置 ...
  plugins: [
    new HelloWorldPlugin({options: true})
  ]
};

compiler 钩子:https://www.webpackjs.com/api/compiler-hooks/

compilation 钩子:https://www.webpackjs.com/api/compilation-hooks/

2.3、webpack 插件分析

首先介绍webpack源码分析方法

  • node --inspect-brk ./node_modules/webpack/bin/webpack.js --config ./webpack.config.js
  • chrome输入 chrome://inspect/
  1. 主要的流程是:


 2.webpack构建的主要钩子:


 3.Tapable

compiler和compilation都继承于Tapable
webpack的插件是基于Tapable的,Tapable允许你添加和应用插件到javascript模块中,类似于 NodeJS的EventEmitter,可以被继承和mixin到其他模块中,详情见官网

Tapable
其中关键的方法是

  • plugin(name:string, handler:function)
  • apply(...pluginInstances: (AnyPlugin|function)[])
  • applyPlugins*(name:string, ...)
  • mixin(pt: Object)
    tapable主要负责处理事件,采用的是发布订阅模式,apply相当于trigger,plugin相当于addEventListener
Tapable.prototype.plugin = function plugin(name, fn) {
    if(Array.isArray(name)) {
        name.forEach(function(name) {
            this.plugin(name, fn);
        }, this);
        return;
    }
    if(!this._plugins[name]) this._plugins[name] = [fn];
    else this._plugins[name].push(fn);
};

plugin方法将插件对应的方法加入一个数组中、注册到事件(name)上,等待apply的时候串行调用/触发

Compilation中做了很多事情,处理编译过程。所对应的方法,如addEntry ,buildModule,processModuleDependencies,createChunkAssets,seal等

转自:https://juejin.cn/post/6844903489458405390 官网:https://www.webpackjs.com/concepts/

原文地址:https://www.cnblogs.com/vickylinj/p/14243518.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


一准备工作umi为react的一个封装比较nice的脚手架。优点当然就是安装方便,开箱即用,集成了诸多好用功能,详见官网。当然缺点就是无法暴露原始的webpack.config.json文件,只能按照官方文档上特定的方法进行修改,而文档却并不完善。项目顺利进行大家笑嘻嘻,一旦遇到偏难怪需求,
webpack在引入两个依赖的包时,可能需要使用shimming,意思是处理代码上的兼容1、在main.js中引入jqueryimport$from'jquery'importappendfrom'./append'//下面的给页面添加元素文件append()2、append.js使用main.js的$向页面中添加元素functionappDomFunc(){
  Happypack (plugin)多线程使用loader编译文件treeshaking删除无用JS代码,依赖ESM规范source-map生产环境一定去掉process.env.XXX配置环境变量,区分各种编译环境splitchunks 代码分离去重DynamicImport动态加载js文件Hot-module-replacement开发环境热更新w
一目录结构├──build//构建相关├──config//配置相关├──src//源代码│├──api//所有请求│├──assets//主题字体等静态资源│
接着第一节的demo现在我们尝试整合一些其他资源,比如图像,看看webpack如何处理。在webpack出现之前,前端开发人员会使用grunt和gulp等工具来处理资源,并将它们从 /src 文件夹移动到 /dist 或 /build 目录中。同样方式也被用于JavaScript模块,但是,像webpack这样的工
webpack的打包原理识别入口文件通过逐层识别模块依赖(Commonjs、amd或者es6的import,webpack都会对其进行分析,来获取代码的依赖)webpack做的就是分析代码,转换代码,编译代码,输出代码最终形成打包后的代码什么是loaderloader是文件加载器,能够加载资源文件,并对这些文件进行
上一篇文章我们在一个demo中见到了webpack的身影,如果从未接触过webpack的同学学完了上一篇文章可能会觉得webpack只是一个“翻译官”,但事实上webpack可不仅仅可以‘翻译’代码,事实上,webpack是一个‘打包’工具,‘打包‘才是webpack的核心任务。打开webpack的官网:webpack中
注:本章将配合Vue详细讲解webpack前提条件1.在开始之前,请确保安装了Node.js和npm的最新版本。使用旧版本,你可能遇到各种问题,因为它们可能缺少webpack功能以及/或者缺少相关package包。在cmd中node-v,npm-v可查看对应的版本和安装情况。2.这里会用到ES6的模块化,如果你
前言、之前我认为对于项目的优化无非是从代码上去优化一些东西,比如循环呀函数式调用呀让你的代码看起来更加的简洁容易懂后来我在面试过程中不断有面试官不断地问了我这些问题所以自己就去研究了一下发现并不是我之前想的那样,一个好的webapck优化的胜过于你在整体代码上
##一、组件component###1.什么是组件?组件(Component)是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码组件是自定义元素(对象)###2.定义组件的方式方式1:先创建组件构造器,然后由组件构造器创建组件方式2:直接创建组件###3.组件的分
 #webpack5概述>webpack是一个现代javascript应用程序的**静态模块打包器(modulebundler)**>>vue-cli脚手架环境,集成了webpack,所以才能对各类文件进行打包处理[webpack官网](https://webpack.js.org/) ##webpack能做什么webpack是一个静态模块打包
//这里导入webpack配置,我用对象的形式表示,当然entry属性上定义的文件要有//constconfig=require("./webpack.config");constconfig={entry:'./src/index.js'};const{join,dirname}=require("path");const{readFileSync,writeFileSync}=requi
安装cnpminstallwebpack-bundle-analyzer-D 修改vue.config.jsmodule.exports={chainWebpack:config=>{if(process.env.use_analyzer){//分析config.plugin('webpack-bundle-analyzer')
webpack打包html插件html-webpack-plugin的使用1.创建这样的测试目录结构1)index.html是即将被打包的文件,你可以随便写一些内容2)index.js是打包的入口文件,你可以写或不写内容2.webpack.config.js的代码如下:/***压缩html需要插件:html-webpack=plugin*插件使用方法:
vueinitwebpacktabbar创建vue项目时出现问题vue:无法加载文件C:\Users\dengqian\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。C:\Windows\System32\WindowsPowerShell\v1.0,找到如上路径,以管理员身份运行powershell.exe即可输入set-ExecutionPolicyRemo
在webpack中使用ECharts【官网教程】1、使用如下命令通过npm 安装EChartsnpminstallecharts--save2、全局引用在main.jsimportechartsfrom'echarts'Vue.prototype.$echarts=echarts;3、运用<divstyle="width:60vw;height:280px;"ref="chart"&
如果没有看过我的上一篇文章,请先移步去看一下哈!时隔一年多,之前写的文章感觉大家还挺喜欢的,一直说要更新下一篇。但是一直没有机会,没时间,还有就是,感觉自己的技术,可能不足以支持我继续往下走。但是经过这个一年多的历练,感觉很多东西考虑的会更周全,不负期待!废话说一堆,步入正题
dist文件配置对应的路由名展示这样的效果可以创建一个本地的服务还可以进行代理项目开发是在src里进行代码逻辑编写./表示本地路径/表示绝对路径(nginx需要配置)
 1、用命令创建webpack模板项目vueinitwebpack 项目名,需要选是否的统一选否,所以的依赖手动添加  2、安装依赖vue-router,elementui,sass-loader,node-sass,axios插件安装路由:npminstallvue-router安装elementu
最近想把蘑菇博客部署到k8s上,作为一名java搬砖工,搬砖人不讲码德,biu一下就把后端各模块的dockerfile和chart包copy过来了,很快啊!接下来就可以愉快的使用helm管理蘑菇后端服务部署了。部署完后端服务后,准备制作前端镜像,发现前端打包后,无法动态读取系统环境变量,这很头疼,难不