今天升级一个Vue项目,需要简化新增组件时的开发流程,具体地说,是需要把某个目录设定为组件文件夹,项目打包的时候自动把此文件夹中的组件文件引入到项目的一个多用途组件并注册到components中。
总体思路是先在要写入引用代码和注册代码的地方用注释写两个插槽标记,再写个脚本把文件夹里的组件读出来,生成引用代码和注册代码,最后简单地把插槽标记替换成生成好的代码。
插槽如下:
<script>
/** slot-import */
export default {
components: {
/** slot-components */
}
}
</script>
读取组件如下:
const fs= require('fs')
const path= require('path')
const componentDir= path.resolve(process.cwd(), './src/components') // 组件文件夹
const componentList = fs.readdirSync(componentDir, {
encoding: 'utf8', withFileTypes: true
})
const componentSet = []
for (let i= 0; i< componentList.length; i++) {
const n= path.resolve(componentDir, componentList[i].name)
componentSet.push([ri.name.match(/^(\S+)\./)[1], n])
}
生成引用和注册代码如下:
let importState= ``
let compoentsState= ``
for (let i= 0; i< componentSet.length; i++) {
const [name, path] = componentSet[i]
importState+= `\nimport `
importState+= name
importState+= ` from `
importState+= `'${path}'`
compoentsState+= `\n ${name},`
}
用代码替换插槽如下:
const theFile = path.resolve(process.cwd(), './src/pages/multiFunc.vue') // 多功能组件文件夹
fs.readFile(theFile, 'utf8', (err, data) => {
if (err) {
console.log('err', err)
}
let code= data
code= code.replace('/** slot-import */', importState)
code= code.replace('/** slot-components */', compoentsState)
console.log(code)
fs.writeFileSync(theFile, code)
})
一开始我想着把脚本放根目录,改一下package.json里的scripts,让webpack在打包前自动运行一下脚本完事。但是写完脚本运行完发现行不通,脚本运行一次之后插槽标记就已经变成生成好的代码了,执行第二次就没用了,哪怕添加逻辑让脚本进行替换,也要面临难以预知的bug,而且很容易发现这个方法可能并不是最佳实践。
我马上想到了webpack的loader,很多项目都依靠loader在项目打包前预处理项目文件中的svg、sass之类的。
所以我把上面改成了预处理器代码,命名为script.js,主体其实没有多大区别,只是把用代码替换插槽部分改成一个函数,接收代码作为参数,返回处理后的代码(代码其他部分可以放到函数外):
module.exports= function(sourceCode) {
let code= sourceCode
code= code.replace('/** slot-import */', importState)
code= code.replace('/** slot-components */', compoentsState)
return code
}
到此为止,脚本部分就完成了。
接下来把它发布到npm上,以便在使用,我使用的命令行(macOS环境)如下:
创建并文件夹
mkdir myloader
cd myloader
初始化,按提示输入配置(后续可以在package.json中查看、修改)
npm init
把写好的脚本文件复制到文件夹内,命名为index.js(和你上面配置的入口文件名一致)
cp ../script.js index.js
发布模块
npm publish
如果没登录,可以登录后操作
npm login
如果出现类似409 Conflict - PUT https://mirrors.cloud.tencent.com/npm/-/user/org.couchdb.user:xxxxxx - user registration disabled,可以用以下命令查看npm的配置项,有可能需要恢复默认值
npm config list
恢复配置项默认值命令为
npm config delete xxxxxx
不出意外,模块就成功发布到npm.js上了,我们可以在项目里进行安装
npm i -D myloader
接下来我们在vue.config.js中添加预处理器配置(链式配置):
chainWebpack(config) {
config.module
.rule('myLoader')
.include
.add(resolve('src/pages/multiFunc.vue'))
.end()
.use('myLoader')
.loader('myLoader')
.end()
}
项目升级完毕。