Webpack 梳理

195 阅读4分钟
  • loader和plugin的区别
    • loader 模块转换器 比如 jsx - js / less - css
    • plugin 扩展插件 比如HtmlWebpackPlugin
  • module chunk bundle分别是什么意思?有什么区别?
    • module 各个源码文件
    • chunk 多个模块的集合 eg:entry/import/splitChunks
    • budle 最终输出的文件
  • babel和webpack的区别?
    • babel js新语法编译工具,不关心模块化
    • webpack 打包构建工具,是多个loader/plugin的集合
  • webpack实现懒加载
    • import() () => import('../../component.js')
    • vue/react异步组件
  • 基本配置
  • 高级配置
  • 优化打包效率(开发环境
    • 自动刷新
    • 热更新
    • DllPlugin
  • 优化打包效率(可用线上
    • babel-loader
    • IngorePulgin
    • noParse
    • happyPack
    • parallelUglifyPlugin
  • 优化产出代码
    • 小图片base64
    • bundle+hase
    • 懒加载
    • 提取公共代码
    • CDN
    • IgnorePlugin
    • production
    • scope hosting
  • 构建流程概述 为什么前端代码要进行构建和打包? (juejin.cn/post/684490… / juejin.cn/post/684490… / juejin.cn/post/684490…
    • webpack就是各种插件组成的集合,这些钩子是通过Tapable串起来的,类比react生命周期,每个生命周期会顺序执行对应的钩子
    • Compiler对象就是webpack的实体(是Tapable的实例),他创建了Compilation对象,Compilation任务执行完毕后会将最终的处理结果返回给Compiler。
    • Compilation是编译阶段的主要执行者,(是Tapable的实例),执行模块创建、依赖收集、分块、打包等主要任务的对象
    • compiler的启动是run方法,run方法里边主要关注两个动作:调用了compile方法;声明了调用compile传入的回调函数onCompiled
      • compile上的钩子:beforeCompile、compile、make(关键钩子)、afterCompile、thisCompilation、compilation
      • compilation上的钩子:finish、seal
      • compilation开始于addEntry方法并结束于addEntry。
  • babel babel-runtime和babel-polyfill的区别?
    • polyfill会污染全局变量
    • runtime则不会,一般如果是提供第三方lib的时候用runtime,慎用polyfill
  • 热加载原理 (juejin.cn/post/684490…
    • watch 编译过程、devServer 推送更新消息到浏览器
    • 浏览器接收到服务端消息做出响应
      • 启动 devServer 的时候,sockjs 在服务端和浏览器端建立了一个 webSocket 长连接,以便将 webpack 编译和打包的各个阶段状态告知浏览器
    • 对模块进行热更新或刷新页面
  • tree sharking原理 (juejin.cn/post/700241…
    • Tree-shaking 的实现一是先标记出模块导出值中哪些没有被用过
      • Make 阶段,收集模块导出变量并记录到模块依赖关系图 ModuleGraph 变量中
      • Seal 阶段,遍历 ModuleGraph 标记模块导出变量有没有被使用
    • 使用 Terser 删掉这些没被用到的导出语句
      • 生成产物时,若变量没有被其它模块使用则删除对应的导出语句
  • 有没有自己实现过plugin (juejin.cn/post/684490…
    • 在它的原型上定义 apply 方法
    • 指定一个触及到 Webpack 本身的事件钩子
    • 操作 Webpack 内部的实例特定数据;
    • 在实现功能后调用 Webpack 提供的 callback
  1. 基本配置
    • 拆分配置和merge (common/dev/prod
    • 启动本地服务 (devServer
    • 处理ES6 (bable
    • 处理样式 (style-loader/css-loader/postcss-loader
    • 处理图片 (小图片base64处理,减少网络请求 url-loader
    • 默认支持 模块化
  2. 高级配置
    • 多入口
      • entry需要配置多个
      • plugins里面需要new 对应的 HtmlWebpackPlugin
      • output里面名字需要更改为变量类似这种 [name].[contenthash:8].js
    • 抽离css文件
      • 首先需要loader里面引入插件MiniCssExtractPlugin 替换掉dev环境的style-loader
      • 配置plugin里面的MiniCssExtractPlugin 对应的拆分后的名字 css/mian.[contenthash:8].css
      • 添加压缩配置插件 optimization: {minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})]}
    • 抽离公共代码 (公共代码和第三方模块
      • splitChunks里面配置cacheGroups: {vendor: '', common: ''}
      • HtmlWebpackPlugin里面加上对应的chunk名字
    • 懒加载 (类似定义一个新chunk
      • setTimeout(() => { import().then(res => {}) }, 1500)
  3. 性能优化
    • 优化打包构建速度 - 开发体验和效率
    • 优化产出代码 - 产品性能
      • 优化babel-loader 增加缓存?cacheDirectory 明确范围 include
      • ignorePlugin 避免引入无用的模块 plugins: new webpack.IgnorePlugin(//, //),直接不引入,不在代码里面 (prod)
      • noParse 避免重复打包 noParse: [/react.min.js$/],引入但是不打包,不会进行模块化的分析 (prod)
      • happyPack 多进程打包 (prod)
      • ParallelUglifyPlugin 开启多进程压缩
      • 自动刷新 watch: true / watchOptions 保存代码之后 页面重新刷新一遍
      • 热更新 新代码生效 网页不刷新 状态不丢失 需要自己去开启哪些模块需要热更新 实现方式???
      • DllPlugin 动态链接库插件
    • webpack性能优化 产出代码
      • 体积更小
      • 合理分包,不重复加载
      • 速度更快 内存使用更少
        • 小图片base64
        • [name].[contenthash:8].js
        • 懒加载
        • 抽离公共模块、第三方代码
        • ingnorePlugin忽略无用代码
        • 使用CDN加速 默认加上前缀cdn地址(publikPath) 上传到CDN上去
        • 使用production (自动开启压缩/vue react自动删掉调试代码/启动tree sharking
        • Scope Hosting 多个函数合并成一个函数,代码体积更小,创建函数作用域更少,可读性更高 ModuleConcatenationPlugin
  4. babel/babel-polyfill/babel-runtime
    • babel-polyfill babel对应的补丁,比如对promise/includes的补充
    • babel-runtime 对应babel-polyfill会污染全局变量,如果是第三方lib的话不合适,这时需要runtime
    • class可以用function模拟
    • promise可以用callback模拟
    • Proxy的功能用object.defineProperty无法模拟,所以proxy不能被polyfill