详细记录前端项目使用import懒加载组件打包失败的踩坑之路

前言:

有些问题真的很玄学,但是出现了你又不得不去解决,哪怕解决完了你还是一脸懵逼,但是解决一次也算累积了一次经验了。

这篇笔记是基于之前的一篇笔记的补充加强版:所以看下去之前建议先移步之前那篇笔记:

关于vue 动态引入(异步加载import和require)组件的方法和坑(按需懒加载组件,动态生成路由)babel-plugin-dynamic-import-node 优化编译速度

由于前几天又遇到一个神坑,所以有了这篇加强版的笔记:

先说说坑:

前端根据后端授权的菜单数据动态生成前端路由地图的时候,一般我们会采用import懒加载的方式来加载路由对应的组件:

return () => import(/* webpackChunkName: "[request]" */ `@/views/${view}`)

本来打包一直都好好的,突然有一次因为某个功能需要安装某个依赖包,然后再执行打包的时候,就不行了。import懒加载的组件路由,访问页面的时候都找不到对应的模块。检查一下才看到,build虽然没有报错,但是生成的dist目录下并没那些懒加载组件对应js文件。

问题原因很明显,就是使用import懒加载组件出了问题。

刨坑:

第一时间怀疑是安装的包导致了webpack版本降低了,因为webpack低版本是不支持import的,所以查了webpack版本,4.x,所以不是它的问题。

然后又重新删了引入的包,还是不行;

再次把node_modules删了,依赖重装,还是不行;
然后想起来之前写过一篇关于组件懒加载的博文章,就是文章开头的那个链接。

当然,无非就是让import组件在打包的时候能够被正确转换成reqiure, 所说需要额外的插件和babel配置(但是之前正常,babel配置没动过,按道理不该怀疑它,但是没办法,问题总要解决)。


安装并在babel配置文件中配置,@/babel/plugin-syntax-dynamic-import,这个依赖就是干这事的。

不过,只需要在babel.config.js文件中配置这个就行了:@babel/preset-env。因为它已经包括了@/babel/plugin-syntax-dynamic-import依赖。


但是做完这些都还不行,我就懵了。因为之前也这么解决过这个问题。


然后又是各种捣鼓,什么招都使了,还是不行。

最后还是回到babel.config.js文件,尝试把这个配置删了'@vue/cli-plugin-babel/preset',奇迹出现了,果然成了。


我为什么会配置@vue/cli-plugin-babel/preset这个?是因为之前别的项目也同时配置了它和@babel/preset-env,import都能正常使用,但是放到这个项目就不行了,所以就很服气。

但正常理解这个预设@vue/cli-plugin-babel/preset其实@babel/preset-env并不冲突,两个预设的功能有重叠,大部分就是把es6的新语法进行转换,和转换vue代码。

而且@vue/cli-plugin-babel/preset这个预设还包含了比如jsx代码的转换,如果你的代码里使用了jsx,配置这个预设就能解决。

但是现在加了这个预设,打包还是有问题,所以只能删了他,仅保存@babel/preset-env这个预设,再单独配置这个依赖:'@vue/babel-preset-jsx', 这样就正常了。

虽然整个过程还是有些懵,好在最后,是搞定了,也不担心安装新依赖的问题了。


但是这个问题出现的根本原因是啥,我还是没搞明白,为什么随便安装了一个其他依赖,import突然就不行了?

而且之前babel配置文件里也没有配置@babel/preset-env这个或@/babel/plugin-syntax-dynamic-import,怎么impport懒加载组件都是没问题的?

然后突然就不行了,需要补充配置import转require的bable配置,不知道有没有大神来解答一下。
最后附上babel的配置:

module.exports = {
  presets: [
    '@vue/babel-preset-jsx',
    [
      '@babel/preset-env',
      {
        'useBuiltIns': 'entry',
        'corejs': 3
      }
    ]
  ],
  'env': {
    'development': {
      'plugins': ['dynamic-import-node']
    }
  }
}

再附上一个比较全的babel.config.js配置,这个是chatgpt3.5生成的,是否之前待验证:

module.exports = {
  presets: [
    // 预设,用于指定babel转换代码的规则和插件
    '@babel/preset-react', // 将JSX语法转换为React.createElement函数调用
    [
      '@babel/preset-env', // 将ES6+代码转换为向后兼容的代码
      {
        // useBuiltIns选项指定如何处理ES6中的新特性,例如Promise和Map。'entry'表示根据需要自动引入polyfill,'usage'表示根据代码中使用的特性自动引入polyfill。
        useBuiltIns: 'entry',
        // corejs选项指定使用的core-js版本。
        corejs: 3,
        // targets选项指定需要支持的浏览器或Node.js版本。
        targets: {
          // 可以使用字符串或对象指定目标环境。
          chrome: '58',
          firefox: '54',
          safari: '11',
          edge: '16',
          node: '8'
        },
        // modules选项指定如何处理模块化代码。'auto'表示根据目标环境自动选择,'commonjs'表示转换为CommonJS模块,'false'表示不转换。
        modules: 'auto',
        // debug选项用于输出Babel的调试信息。
        debug: true,
        // include选项用于指定需要转换的文件路径。
        include: [],
        // exclude选项用于指定不需要转换的文件路径。
        exclude: [],
        // loose选项用于指定是否使用松散模式转换代码。
        loose: true,
        // shippedProposals选项用于指定是否支持实验性语法。
        shippedProposals: true,
        // forceAllTransforms选项用于强制转换所有代码,即使目标环境已经支持该特性。
        forceAllTransforms: true,
        // ignoreBrowserslistConfig选项用于忽略.browserslistrc文件中的配置。
        ignoreBrowserslistConfig: true,
        // configPath选项用于指定.babelrc文件的路径。
        configPath: './.babelrc'
      }
    ],
    // @vue/cli-plugin-babel/preset是Vue CLI的Babel预设,用于转换Vue.js代码。
    '@vue/cli-plugin-babel/preset',
    // @vue/babel-preset-jsx是Vue.js的JSX预设,用于转换Vue.js中的JSX代码。
    '@vue/babel-preset-jsx'
  ],
  plugins: [
    // 插件,用于扩展babel的功能
    '@babel/plugin-transform-runtime', // 将代码中的公共部分提取到单独的模块中,避免重复打包
    '@babel/plugin-proposal-class-properties' // 支持类属性的语法
  ],
  env: {
    // 环境配置,用于指定不同的环境下的babel配置
    development: {
      presets: [
        '@babel/preset-env',
        '@babel/preset-react'
      ],
      plugins: [
        'dynamic-import-node'
        '@babel/plugin-transform-runtime',
        '@babel/plugin-proposal-class-properties'
      ]
    },
    production: {
      presets: [
        ['@babel/preset-env', { modules: false }], // 将ES6+代码转换为向后兼容的代码,同时禁用模块转换,交由打包工具处理
        '@babel/preset-react'
      ],
      plugins: [
        'uglifyjs-webpack-plugin',
        '@babel/plugin-transform-runtime',
        '@babel/plugin-proposal-class-properties'
      ]
    }
  },
  ignore: [
    // 忽略文件,用于指定babel忽略哪些文件
    '*.test.js', // 忽略测试文件
    'node_modules' // 忽略node_modules目录下的文件
  ],
  overrides: [
    // 覆盖配置,用于指定特定文件的babel配置
    {
      test: /\.jsx$/, // 匹配所有以.jsx结尾的文件
      presets: ['@babel/preset-react'] // 指定只使用@babel/preset-react预设
    }
  ],
  sourceType: 'module', // 源代码类型,用于指定babel解析的代码类型
  compact: true, // 是否压缩代码
  minified: true, // 是否最小化代码
  comments: false, // 是否保留注释
  retainLines: true, // 是否保留代码行数
  sourceMaps: true, // 是否生成source map
  babelrc: false, // 是否使用.babelrc文件
  configFile: false, // 是否使用babel.config文件
  passPerPreset: true, // 是否将每个预设的结果传递给下一个预设
  cwd: process.cwd(), // 当前工作目录
  root: process.cwd(), // 项目根目录
  rootMode: 'root', // 项目根模式
  envName: process.env.NODE_ENV // 当前环境名称
};

你可能感兴趣的:(前端,技能,前端部署,前端,webpack,vue.js,前端框架)