-
Notifications
You must be signed in to change notification settings - Fork 5
Description
发现问题
在使用VUE CLI3生成项目时,引入未打包的组件(这里的组件发布成了npm包,抛出的仍然是原生态的.vue
文件,由于该组件采用VUE CLI3调试和生成,且目标环境是VUE CLI3,因此组件可以和VUE CLI3业务代码完美契合,同时也可以防止二次打包问题,当然有使用一些VUE CLI3不包含的特殊webpack loader的VUE组件仍然是推荐打包后发布),发现组件的版本更新后,启动项目显示的仍然是旧版本的组件。
组件(npm包)结构
├── packages
│ └── xxx
│ ├── src
│ │ └── xxx.vue
│ ├── theme
│ │ └── index.scss
│ ├── index.js
│ └── package.json
package.json
中的main
字段指向了index.js
。
VUE CLI项目中引入
// src/main.js
import xxx from 'xxx'
import 'xxx/theme/index.scss'
Vue.use(xxx)
定位问题
第一反应是与缓存相关,于是使用VUE CLI3/开发/webpack相关/审查项目的 webpack 配置中的vue inspect
功能输出了当前项目的Webpack配置,寻找出与cache-loader
相关的配置信息:
/* config.module.rule('vue') */
{
test: /\.vue$/,
use: [
/* config.module.rule('vue').use('cache-loader') */
{
loader: 'cache-loader',
options: {
cacheDirectory: 'G:\\dolphin-vuc-cli3\\dolphin_issc\\node_modules\\.cache\\vue-loader',
cacheIdentifier: 'b466c286'
}
},
/* config.module.rule('vue').use('vue-loader') */
{
loader: 'vue-loader',
options: {
compilerOptions: {
preserveWhitespace: false
},
cacheDirectory: 'G:\\dolphin-vuc-cli3\\dolphin_issc\\node_modules\\.cache\\vue-loader',
cacheIdentifier: 'b466c286'
}
}
]
},
/* config.module.rule('js') */
{
test: /\.m?jsx?$/,
exclude: [
function () { /* omitted long function */ }
],
use: [
/* config.module.rule('js').use('cache-loader') */
{
loader: 'cache-loader',
options: {
cacheDirectory: 'G:\\dolphin-vuc-cli3\\dolphin_issc\\node_modules\\.cache\\babel-loader',
cacheIdentifier: 'b77d1c56'
}
},
/* config.module.rule('js').use('babel-loader') */
{
loader: 'babel-loader'
}
]
},
发现cache-loader
匹配了/\.vue$/
和/\.m?jsx?$/
文件,因此需要去除cache-loader
并观察是否是该loader
引起的问题。
更改webpack配置文件
由于VUE CLI3项目使用webpack-chain链式操作在源码中动态生成Webpack配置,因此有两种方式更改VUE CLI3项目的配置信息:
vue.config.js
:使用webpack-chain
在vue.config.js
中覆盖默认的config.module.rule('vue')
和config.module.rule('js')
,去除两者的缓存配置。@vue/cli-service、@vue/cli-plugin-babel
:更改config.module.rule('vue')
和config.module.rule('js')
配置所在的源码文件。
这里采用第二种方式进行验证,去除config.module.rule('vue')
中的缓存配置:
// @vue/cli-service/lib/config/base.js
webpackConfig.module
.rule('vue')
.test(/\.vue$/)
// .use('cache-loader')
// .loader('cache-loader')
// .options(vueLoaderCacheConfig)
// .end()
.use('vue-loader')
.loader('vue-loader')
.options(Object.assign({
compilerOptions: {
preserveWhitespace: false
}
// 第一次尝试的时候没注释这里,只注释了cache-loader,导致问题一直排查不出来
// 花费了两个晚上时间,代价有点大(因为第一次尝试就将vue-loader排除在外)
// }, vueLoaderCacheConfig))
}))
去除config.module.rule('js')
中的缓存配置:
// @vue/cli-plugin-babel/index.js
const jsRule = webpackConfig.module
.rule('js')
.test(/\.m?jsx?$/)
.exclude
.add(filepath => {
// always transpile js in vue files
if (/\.vue\.jsx?$/.test(filepath)) {
return false
}
// exclude dynamic entries from cli-service
if (filepath.startsWith(cliServicePath)) {
return true
}
// check if this is something the user explicitly wants to transpile
if (transpileDepRegex && transpileDepRegex.test(filepath)) {
return false
}
// Don't transpile node_modules
return /node_modules/.test(filepath)
})
.end()
// .use('cache-loader')
// .loader('cache-loader')
// .options(api.genCacheConfig('babel-loader', {
// '@babel/core': require('@babel/core/package.json').version,
// '@vue/babel-preset-app': require('@vue/babel-preset-app/package.json').version,
// 'babel-loader': require('babel-loader/package.json').version,
// modern: !!process.env.VUE_CLI_MODERN_BUILD,
// browserslist: api.service.pkg.browserslist
// }, [
// 'babel.config.js',
// '.browserslistrc'
// ]))
// .end()
更改源码后,验证发现是cache-loader
引起的问题,缩小范围发现是vue-loader
的缓存配置引起的问题。
结论
VUE CLI3缓存旧版本的VUE组件(npm包)是由于vue-loader
中配置了缓存而引起的,并且发现VUE CLI3的 源码中并没有可以关闭该缓存的配置项,因此这里提供了以下解决方案:
1、对VUE CLI官方提出 issue ,等待官方解决该问题(目前仍然没有解决)。
2、如果需要更新组件版本,首先删除node_modules
下的.cache
文件,然后更新组件版本启动项目。
3、更给vue.config.js
,去除config.module.rule('vue')
中的缓存配置。
参考链接
- webpack loader - webpack doc
- VUE CLI3/开发/webpack相关/审查项目的 webpack 配置 - vue cli 3 doc
- webpack-chain - webpack tool github