自定义项目模板开发
在haha-cli-dev-template 这个模块下,新建模板 haha-cli-dev-template-custom-vue3。
修改 package.json , 添加 main 字段
“main”: “index.js”
添加 index.js
function install(options) { console.log(options); } module.exports = install 复制代码
发布到 npm
数据库添加一条新的数据
自定义模板安装逻辑开发
const log = require('npmlog')
const fse = require('fs-extra')
const ejs = require('ejs')
let targetPath
async function install(options) {
try {
const templatePath = options.templatePath
const dirs = fs.readdirSync(templatePath)
const filePath = path.resolve(templatePath, dirs[0])
targetPath = path.resolve(process.cwd(), options.projectInfo.project)
fse.ensureDirSync(filePath)
fse.ensureDirSync(targetPath)
fse.copySync(filePath, targetPath)
} catch (error) {
throw error
} finally {
log.info('模板安装成功')
}
const ignore = ['**/node_modules/**', ...options.template?.ignore.split(',')]
await ejsRender(ignore, options)
}
//ejs渲染=>将模板中的转成模板中package.json定义的版本
function ejsRender(ignore, options) {
return new Promise((resolve, reject) => {
//得到文件夹下除去ignore的所有路径,
require('glob')(
'**',
{
ignore,
cwd: targetPath,
nodir: true
},
(err, files) => {
if (err) {
reject(err)
}
Promise.all(
files.map(file => {
//得到每一个文件的具体路径
const filePath = path.join(targetPath, file)
return new Promise((resolve1, reject1) => {
//解析文件
ejs.renderFile(filePath, options.projectInfo, {}, function (err, str) {
if (err) {
reject1(err)
} else {
//使用renderFile得到的str是字符串,需要转成文件
fse.writeFileSync(filePath, str)
resolve1(str)
}
})
})
})
)
.then(() => resolve(files))
.catch(err => reject(err))
}
)
})
}
module.exports = install
...
//记得加上bundledDependencies 打包的时候将以下的插件打包进入 或者将这些包写入dependencies 生成环境使用(推荐)
"bundledDependencies": [
"npmlog",
"fs-extra",
"glob",
"ejs"
]
...
//自定义安装
async installCustomTemplate() {
if (await this.pkg.exists()) {
const rootFile = this.pkg.getRootFilePath()
if (fs.existsSync(rootFile)) {
const templatePath = path.resolve(this.pkg.cacheFilePath, 'template')
const options = { templatePath, projectInfo: this.projectInfo, template: this.template }
const code = `require('${rootFile}')(${JSON.stringify(options)})`
const ret = await execAysnc('node', ['-e', code], {
cwd: process.cwd(), //cwd 子进程的当前工作目录
stdio: 'inherit' //inherit 将相应的stdio传给父进程或者从父进程传入,相当于process.stdin,process.stout和process.stderr
})
if (ret === 0) {
log.success('命令执行成功')
} else {
throw new Error('命令执行成功失败')
}
}
}
}