前言:
有些问题真的很玄学,但是出现了你又不得不去解决,哪怕解决完了你还是一脸懵逼,但是解决一次也算累积了一次经验了。
这篇笔记是基于之前的一篇笔记的补充加强版:所以看下去之前建议先移步之前那篇笔记:
关于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 // 当前环境名称
};