Webpack-plugin-loader与Eslint

Webpack学习目标

  • 能够使用webpack搭建任意的前端架构环境(v4v5都要会使用)
  • 尽可能多地了解webpack工作流程、底层原理,以及与vitegulprollup等工具的差异与优劣
  • 尽可能多地实践一些webpack构建优化技巧(运行速度、代码质量)

Webpack认识

  • 目前最流行的前端构建工具
  • 作用就是将模块及其依赖编译打包成浏览器能够普遍兼容的优质代码或静态资源
  • 理论上webpack可以对任意的文件进行编译打包。
  • webpack是运行到node环境中的,支持CommonJS模块化语法
  • webpack它是基于配置文件的(定制化特点强)
  • 版本:目前大部分公司中用的是v4版本,最近新出了v5版本

webpack安装

  • webpack-cli
    • 全局安装+本地安装
    • 有很多好用的webpack相关命令
  • webpack
    • 全局安装+本地安装
    • 它是webpack的核心代码包括webpack API和核心插件所在的包。

webpack配置

  • 配置入口和出口,实现build打包功能
  • 配置本地服务,以便开发环境使用
  • 自动清除dist目录,添加文件hash值,开启编译进度条、开启代码压缩
  • 区分开发环境和生产环境
  • src中的js代码编译成浏览器能够普遍兼容的ES5代码
  • 在当前环境下支持jsx语法
  • 配置eslint,实现对代码的检测

webpack文件配置

  • 代码语法是CommonJs模块
  • 导出方式
    • module.exports={}
    • module.exports=function(){return{}}
    • module.exports=()=>{return {}}
    • module.exports=()=>({})
module.exports=()=>({
    entry:{//入口配置(建议在配置入口文件时使用绝对路径)
        app:path.resolve(__dirname,'../src/main.js')
    },
    output:{//出口配置
        filename:'js/[]'
    }
})

自定义loader

  • 每一个loader都是一个函数
  • 接收一种文件(对象或字符串),最终返回另外一种文件(对象、字符串或JS代码)
module.exports=function(source){
    //使用任何第三方js模版do something
    
    //如果一个loader不用与webpack规则的最后一个loader,不要抛出js代码直接return 一个值就可以了
    //不是最后一个loader
    return result
    //es6模块化
    return `export default ${JSON.stringify(result)}`
    //CommonJs
    return `module.exports=${JSON.stringify(result)}`
}

自定义plugin

  • 每一个plugin本质上都是一个class
  • 插件函数或类的prototype上定义一个apply方法
    • 指定要绑定到的webpack事件钩子
    • 处理webpack内部实例数据
    • 功能完成后调到webpack提供的回调
    • 最重要的两个资源complilercompilation对象
// 一个 JavaScript 类
class MyExampleWebpackPlugin {
  // 在插件函数的 prototype 上定义一个 apply 方法,以 compiler 为参数。
  apply(compiler) {
    // 指定一个挂载到 webpack 自身的事件钩子。
    compiler.hooks.emit.tap(
      'MyExampleWebpackPlugin',
      (compilation, callback) => {
        console.log('这是一个示例插件!');
        console.log(
          '这里表示了资源的单次构建的 `compilation` 对象:',
          compilation
        );

        // 用 webpack 提供的插件 API 处理构建过程
        compilation.addModule(/* ... */);

        callback();
      }
    );
  }
}

webpack开发环境优化

开发环境优化标准:运行速度尽量快

  • devtool:inline-source-map

    • 便于调试代码(直接定位源代码位置)
    • 使用devtool会减低运行速度
  • 关闭watch监听代码依赖图的变化

    • v5中使用hot:true实现热更新
    • 提高运行速度
  • 开启memory缓存

    • 提高运行速度
  • 在使用loaderplugin时,使用excludeinculde

    • 缩小搜索范围
    • 提高运行速度
  • 巧用resolve属性

    • 对路径进行优化,缩小搜索范围
    • 在不使用npm run link时候,设置symlinks:false提升解析速度
  • 使用thread-loader

    • 开启多线程构建,提高构建速度
    • 需要注意硬件配置
  • 使用cache-loader

    • 对“指定文件模块”进行缓存
    • 但对于经常要更新的不要缓存,会导致热更新失效
    • 提高运行速度
  • 使用speed-measure-webpack-plugin

    • 测量你的webpack构建速度

webpack生产环境优化

生产环境优化标准:提高打包后代码的质量

  • devtool:source-map

    • 打包后会为每一个bundle生成.map文件
    • 用于打包后代码之间关系映射
  • chunks拆分

    • 前端代码使用()=>import动态导入技术

      • 需要@babel/plugin-syntax-dynamic-import
      • 推荐使用
    • optimization.splitChunkssplit-chunks-plugin

      • 实现手动代码分离,用得很少
  • vender抽离

    • entry入口中对多个chunk中重复代码进行抽离
entry:{
    vendor:['react'],
     app:{
         dependOn:'vendor',
          import:path.resolve(__dirname,'../foo/main.js')
     }
}
  • bundle分析技术

    • 使用webpack-bundle-analyzer对代码依赖图进行人工分析
  • 使用Tree Shaking技术

    • 用于把src中的“死代码”(未使用的代码)移除掉,以节省打包后代码的体积
    • package.json中添加sideEffects:false,该功能只对mode:production起作用
  • 抽离css并压缩

    • 使用mini-css-extract-plugin抽离css
    • 使用css-minimizer-webpack-plugin
  • terser压缩

    • 使用terser-webpack-plugin集成terser高性能压缩

常见loader

  • babel-loader使用babel加载es6代码并将其转换为es5
  • html-loaderHTML导出为字符串,需要传入静态资源的引用路径
  • markdown-loadermarkdown编译为HTML
  • syle-loader将模块导出的内容作为样式添加到DOM
  • sass-loader加载·并编译sass/scss文件为css文件
  • vue-loader编译vue文件

常见plugin

eslint配置

  • 语法是CommonJS语法

  • 意义:协同开发保证代码规范和一致性

  • 使用的插件配置eslint

    • v4中,使用eslint-loader
    • v5中,使用eslint-webpack-plugin
  • 不同的项目,我们需要安装不同的ESLint检测器

  • EsLint的配置文件有六种,.eslintrc.js优先级最高

  • 解决ESLint报错或警告的问题

    • 找到报错的地方或警告的地方进行修改
    • 找到ESLint的规则名称并修改它的检测级别
    • 使用ESLint注释包裹代码,忽略代码的检测
    • 找到webpack配置文件将ESLint注释掉
      • //eslint-disable-line
      • /*eslint-disable*//*eslint-enable*/
      • /*eslint-disable no-var*/ /* eslint-enable no-var*/
    • 在项目的根目录添加,.eslintigore文件(推荐)
  • 配置文件

    module.exports={
        //配置解析器
        "parserOptions": {
            "ecmaVersion": 6,//默认设置为3,5可以使用6,7,8,9也可以指定年号(设置ES版本)
            "sourceType": "module",//设置代码类型,默认是“script”如果使用ESMmodule,设置为"module"
            "ecmaFeatures": {//配额外的语言特性
                "jsx": true,//使用"jsx"
                "impliedStrict":true//启用全局strict mode(要求ecmaVersion是5或更高)
            }
        },
        //默认使用esprima作为解析器,可以指定为其他解析器(1.必须为一个node模块2.必须符合parser interface)
        "parser":"esprima",
        "rules": {
            "semi": "error"
        },
        "plugins":["a-plugin"],//配置插件
        "processor":"a-plugin/a-processor"//指定配置处理器(从另一种文件提取或在预处理中转换为JavaScript代码)
        ,
        "overrides":[//为特定类型的文件指定处理器
               {
                    "files":["*.md"],
                     "processor":"a-plugin/markdown"
                }
        ],
        "env":{//配置预定义全局变量,环境
            "browser":true,
             "node":true
        }
        
    	
    }
    

babel配置

  • 配置预设

    • 什么是预设?就是一些比较大的javaScript语法版本。预设不一定能够编译所有的小语法
    • @babel/corebabel编译器的核心代码,最新版本v7
    • @babel/preset-env是一个babel预设,用于编译ES6+语法
    • @babel/preset-react是一个babel预设,用于编译jsx语法
    • @babel/preset-typescript,是一个babel预设,用于编译ts语法
  • 配置插件

    • 什么是插件?用于弥补预设不能编译的小语法问题
  • babel的配置文件

    • babel.config.js用于全项目范围的配置
    • .babelrc.json用于package级别的配置
  • 配置文件

    module.exports={
        presets:[//配置预设
            ['@babel/preset-env',{}]
        ],
        plugins:[//配置插件,用于弥补预设不能编译的小语法问题
            ["@babel/plugin-proposal-decorators",{"legacy":true}],
            ["@babel/plugin-proposal-class-properties",{}]
        ],
        env:{//基于环境配置babel
            development:{
                plugins:[...]
            },
            production:{
                plugins:[...]
            }
        }
    }
    

webpack 面试题

  • LoaderPlugin的区别

    • loader本质就是一个函数用于对对应的资源进行转换,因为webpack只认识JavaScript
    • plugin就是插件(具有apply实例方法的类),是基于事件流的框架Tapable
    • 插件可以扩展webpack的功能,原理:在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,并通过webpack提供的api改变输出结果
    • loadermodule.rules中配置,pluginplugins数组中单独配置,每一项都是plugin的一个实例
  • Webpack构建流程

    webpack的运行流程是一个串行的过程,具体流程如下:

    • 初始化参数

      • 合并配置文件和shell语句中的参数得到最终参数
    • 开始编译

      • 用上一步得到的参数初始化Compiler对象
      • 加载所有配置的插件
      • 执行对象的run方法开始执行编译
    • 确定入口

      • 根据配置中的entry找出所有的入口文件
    • 编译模块

      • 调用所有配置的loader对模块进行翻译
      • 再对模块的依赖模块进行翻译直到所有模块都翻译完毕
    • 完成模块编译

      • 经过loader翻译后得到最终翻译内容,以及它们的依赖关系
    • 输出资源

      • 根据入口和模块的依赖关系,组装为一个个的chunk文件
      • 再把一个个的chunk文件加入到输出列表中
    • 输出完成

      • 再确定好输出内容后,根据配置确定输出的路径和路径名,写入到文件系统
  • 提高效率的插件

    • webpack-merge:提取公共配置,减少重复配置代码
    • webpack-dashboard:可以更友好的展示相关打包信息
    • size-plugin:监视资源体积变化,尽早发现问题
  • source map

    • source map是将编译、打包、压缩后的代码 映射回源代码的过程,打包压缩后的代码不具有良好的可读性,调试源码就需要soucre map
    • map文件只要不打开开发者工具,浏览器是不会加载的。
    • 线上环境有三种处理方案
      • hidden-source-map:借助第三方错误监控平台Sentry使用
      • nosources-source-map:只会显示具体行数以及查看源码的错误栈,安全性比sourcemap
      • sourcemap:通过nginx设置将.map文件只对白名单开发(公司内网)
  • 模块打包原理

    • Webpack实际上为每个模块创造了一个可以导出和导入的环境,本质上并没有修改 代码的执行逻辑,代码执行顺序与模块加载顺序也完全一致。
  • 文件监听原理

    • 当发现源码发生变化时,自动构建出新的输出文件

    • 开启监听模式

      • 启动webpack命令时,带上--watch参数
      • 在配置webpack.config.js中设置watch:true
    • 缺点:每次需要手动刷新浏览器

    • 原理:轮询判断文件的最后编辑时间是否变化,如果某个文件发生了变化,并不会立刻告诉监听者,而是先缓存起来,等 aggregateTimeout 后再执行。

      module.export = {    // 默认false,也就是不开启    
          watch: true,    
          // 只有开启监听模式时,watchOptions才有意义    
          watchOptions: {        
              // 默认为空,不监听的文件或者文件夹,支持正则匹配        
              ignored: /node_modules/,        
              // 监听到变化发生后会等300ms再去执行,默认300ms        
              aggregateTimeout:300,        
              // 判断文件是否发生变化是通过不停询问系统指定文件有没有变化实现的,默认每秒问1000次        
              poll:1000    
          }
      }
      
  • 热更新原理

    • 热更新缩写为HMR,这个机制可以做到不用刷新浏览器就可以将旧模块更新为新模块
    • webpack dev serve(WDS)与浏览器之间维护了一个websocket长连接
      • 当本地资源发生变化时,WDS会向浏览器推送更新,并带上构建时的hash,让客户端与上一次资源进行对比
      • 如果客户端比对出差异会向WDS发起Ajax请求来获取更改内容(文件列表、hash),这样客户端再借助这些信息继续向WDS发起jsonp请求获取该chunk的增量更新
      • 拿到增量更新之后,由HotModulePlugin来完成,提供了相关API以供开发者根据自身场景进行处理。像react-hot-loadervue-loader都是借助这些API实现的HMR
  • bundle体积进行监控和分析

    • 使用VSCode插件Import Cost帮助我们对引入模块的大小进行实时监控
    • 使用webpack-bundle-analyzer生成bundle的模块组成图
    • bundlesize 工具包可以进行自动化资源体积监控。
  • 文件指纹

    文件指纹指的是打包后输出的文件名的后缀

    • hash:只要项目有变化,整个项目的hash值就会改变
    • chunkhash:和webpack打包的chunk有关,不同的entry会出不同的chunkhash
    • contenthash:根据文件内容来定义hash,文件内容不变,则contenthash不变
  • CSS的文件指纹

  • 图片的文件指纹

  • 保证各个loader按照预想方式工作

  • 优化 Webpack 的构建速度

  • 代码分割

  • 编写loader

  • 编写Plugin

  • Babel原理

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值