HMR_souce-map_oneof_babel缓存优化

本文详细介绍了webpack的热模块替换(HMR)、source-map的配置与选择,以及如何优化开发环境和生产环境的构建速度与调试体验。重点讲解了HMR在css和js中的实现,source-map的不同类型及其应用场景,以及如何根据需求选择合适的source-map类型。同时,文章还提供了webpack配置示例,包括babel缓存和html入口的设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HMR: css的style-loader自己实现了, 只需要devServe中hot: true即可, html不需要, 因为只有一个文件, 不要热模块替换, 改了就是改了, 不牵连其他, js中需要配置:

// 通过module.hot判断是否开启了HMR
if (module.hot) {
  // 如果开启了就去检测某个引入的文件是否变化, 如果变化了就单独重新执行该模块里引入的方法或对象
  module.hot.accept('./print', () => {
    print()
  })
}

souce-map在devtools中设置, 有好些不同值, 代表不同的用法, 开发环境常用eval-source-map, 生产环境常用source-map, 具体如下

  • [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

    1. source-map:外部
      错误代码准确信息 和 源代码的错误位置

    2. inline-source-map:内联
      只生成一个内联source-map
      错误代码准确信息 和 源代码的错误位置

    3. hidden-source-map:外部
      错误代码错误原因,但是没有错误位置
      不能追踪源代码错误,只能提示到构建后代码的错误位置

    4. eval-source-map:内联
      每一个文件都生成对应的source-map,都在eval
      错误代码准确信息 和 源代码的错误位置

    5. nosources-source-map:外部
      错误代码准确信息, 但是没有任何源代码信息

    6. cheap-source-map:外部
      错误代码准确信息 和 源代码的错误位置
      只能精确的行

    7. cheap-module-source-map:外部
      错误代码准确信息 和 源代码的错误位置
      module会将loader的source map加入

  • 内联 和 外部的区别及选择

    1. 外部生成了文件,内联没有 2. 内联构建速度更快

    开发环境:速度快,调试更友好
    速度快(eval>inline>cheap>…)
    eval-cheap-souce-map
    eval-source-map
    调试更友好
    souce-map
    cheap-module-souce-map
    cheap-souce-map

    –> eval-source-map

    生产环境:源代码要不要隐藏? 调试要不要更友好
    内联会让代码体积变大,所以在生产环境不用内联
    nosources-source-map 全部隐藏
    hidden-source-map 只隐藏源代码,会提示构建后代码错误信息

    –> source-map / cheap-module-souce-map

oneof即命中一次就停止检索loader

babel缓存在babel-loader的options中设置cacheDirectory为true即可, 兼容性处理的代码是固定的, 一般不需要每次都要更新

具体配置见下方:


/* eslint-disable */
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
process.env.NODE_ENV = 'development'

module.exports = {
  // 增加html入口解决HMR开启后更改html页面不更新问题
  entry: ['./src/js/index.js', './src/index.html'],
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // 不止匹配一次的放在外面, 但是里面也可以放一个
      {
        // 使用oneOf让每个test匹配即下面的每一个对象只命中一次就停止, 因为下面只有一个处理, 匹配到了不停止继续匹配对性能浪费
        oneOf: [
          {
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
          },
          {
            test: /\.html$/,
            loader: 'html-loader'
          },
          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: {
              presets: [
                [
                  // 需要这个插件来按照corejs规则来编译
                  '@babel/preset/env',
                  {
                    // 按需引入
                    useBuildIns: 'usage',
                    corejs: { version: 3 },
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
                  }
                ]
              ],
              // 开启babel缓存, 有时候js改了一部分但是缓存的兼容性处理方法很多时候不用改
              cacheDirectory: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    // g-zip压缩
    compress: true,
    port: 3000,
    // 自动打开浏览器
    open: true,
    // 使用HMR热模块替换
    hot: true
  },
  /*
  [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

  source-map:外部
    错误代码准确信息 和 源代码的错误位置
  inline-source-map:内联
    只生成一个内联source-map
    错误代码准确信息 和 源代码的错误位置
  hidden-source-map:外部
    错误代码错误原因,但是没有错误位置
    不能追踪源代码错误,只能提示到构建后代码的错误位置
  eval-source-map:内联
    每一个文件都生成对应的source-map,都在eval
    错误代码准确信息 和 源代码的错误位置
  nosources-source-map:外部
    错误代码准确信息, 但是没有任何源代码信息
  cheap-source-map:外部
    错误代码准确信息 和 源代码的错误位置 
    只能精确的行
  cheap-module-source-map:外部
    错误代码准确信息 和 源代码的错误位置 
    module会将loader的source map加入

  内联 和 外部的区别:1. 外部生成了文件,内联没有 2. 内联构建速度更快

  开发环境:速度快,调试更友好
    速度快(eval>inline>cheap>...)
      eval-cheap-souce-map
      eval-source-map
    调试更友好  
      souce-map
      cheap-module-souce-map
      cheap-souce-map

    --> eval-source-map

  生产环境:源代码要不要隐藏? 调试要不要更友好
    内联会让代码体积变大,所以在生产环境不用内联
    nosources-source-map 全部隐藏
    hidden-source-map 只隐藏源代码,会提示构建后代码错误信息

    --> source-map / cheap-module-souce-map
*/
  devtool: 'source-map'

}

### 关于 `__VUE_HMR_RUNTIME__` 未定义错误的原因分析 当开发者遇到 `__VUE_HMR_RUNTIME__ is not defined` 的错误时,通常是因为热重载(Hot Module Replacement, HMR)机制未能正常初始化。此问题可能由以下几个原因引起: 1. **Vue 版本不匹配** 如果项目使用的 Vue 版本与构建工具版本不一致,可能会导致 HMR 初始化失败[^2]。 2. **开发服务器配置不当** Webpack 或 Vite 配置文件中的 HMR 设置可能存在缺失或冲突的情况。例如,在 Webpack 中未启用 `devServer.hot` 参数或将 `hotOnly` 设为 `true` 可能会引发该问题[^3]。 3. **插件加载顺序异常** 某些情况下,第三方库或插件的加载顺序可能导致 HMR 运行环境无法正确挂载到全局对象上[^4]。 --- ### 解决方案 #### 方法一:确认 Vue 和依赖项版本一致性 确保项目的 Vue 版本与其所依赖的工具链版本相兼容。可以通过运行以下命令来检查当前安装的包及其版本号: ```bash npm list vue webpack vite ``` 如果发现版本存在差异,则可以尝试更新至最新稳定版或者回退到已知稳定的组合版本。对于 Vue CLI 用户来说,执行如下操作即可完成升级过程: ```bash npm install @vue/cli-service@latest --save-dev ``` #### 方法二:调整 Webpack/Vite 配置以支持 HMR 针对基于 Webpack 构建的应用程序,请验证是否存在以下设置选项并适当修改它们: - 在 `webpack.config.js` 文件中开启热模块替换功能: ```javascript module.exports = { devServer: { hot: true, liveReload: false // 推荐关闭实时刷新以便充分利用HMR优势 } }; ``` 而对于采用 Vite 工具创建的新一代前端工程而言,默认已经集成了现代化特性如快速冷启动以及高效的增量编译能力;因此只需简单地保证官方文档推荐的基础结构被遵循就足以解决问题了。不过仍然建议显式声明相关字段作为保险措施之一: ```javascript export default defineConfig({ server: { hmr: { overlay: false } // 自定义提示覆盖行为 }, }); ``` #### 方法三:清理缓存重新构建项目 有时旧数据残留也会干扰新逻辑生效,故而有必要彻底清除node_modules目录后再重新下载全部必要组件再试一次看看效果如何改善。 ```bash rm -rf node_modules package-lock.json yarn.lock npm cache clean --force npm install ``` #### 方法四:排查是否有其他脚本污染全局作用域 最后还应留意是否由于引入外部资源不当而导致意外篡改到了原本属于框架内部管理的部分变量名空间情况发生过呢?如果有则需定位具体位置加以修正才行哦! --- ### 示例代码片段展示正确实现方式 以下是利用 Vue 官方提供的 API 来检测 HMR 是否可用的一个例子: ```javascript if (module.hot) { console.log('HMR is enabled.'); } else { throw new Error('__VUE_HMR_RUNTIME__ is undefined'); } ``` 另外附带一段简单的计数器演示如何结合 HMR 使用场景下的基本写法供参考学习之用: ```html <template> <div>{{ count }}</div> </template> <script> import { ref } from 'vue'; let _count; // Export setup function instead of exporting object directly. function createComponent() { const count = (_count = ref(0)); setInterval(() => { _count.value++; }, 1000); return { count }; } if (module.hot) { module.hot.dispose((data) => { data._count = _count; }); module.hot.accept((data) => { if (!data || !('_count' in data)) { return; } _count = data._count; }); } export default { setup: createComponent }; </script> ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值