自定义项目模板开发

在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
数据库添加一条新的数据
image.png

自定义模板安装逻辑开发

  1. const log = require('npmlog')
  2. const fse = require('fs-extra')
  3. const ejs = require('ejs')
  4. let targetPath
  5. async function install(options) {
  6. try {
  7. const templatePath = options.templatePath
  8. const dirs = fs.readdirSync(templatePath)
  9. const filePath = path.resolve(templatePath, dirs[0])
  10. targetPath = path.resolve(process.cwd(), options.projectInfo.project)
  11. fse.ensureDirSync(filePath)
  12. fse.ensureDirSync(targetPath)
  13. fse.copySync(filePath, targetPath)
  14. } catch (error) {
  15. throw error
  16. } finally {
  17. log.info('模板安装成功')
  18. }
  19. const ignore = ['**/node_modules/**', ...options.template?.ignore.split(',')]
  20. await ejsRender(ignore, options)
  21. }
  22. //ejs渲染=>将模板中的转成模板中package.json定义的版本
  23. function ejsRender(ignore, options) {
  24. return new Promise((resolve, reject) => {
  25. //得到文件夹下除去ignore的所有路径,
  26. require('glob')(
  27. '**',
  28. {
  29. ignore,
  30. cwd: targetPath,
  31. nodir: true
  32. },
  33. (err, files) => {
  34. if (err) {
  35. reject(err)
  36. }
  37. Promise.all(
  38. files.map(file => {
  39. //得到每一个文件的具体路径
  40. const filePath = path.join(targetPath, file)
  41. return new Promise((resolve1, reject1) => {
  42. //解析文件
  43. ejs.renderFile(filePath, options.projectInfo, {}, function (err, str) {
  44. if (err) {
  45. reject1(err)
  46. } else {
  47. //使用renderFile得到的str是字符串,需要转成文件
  48. fse.writeFileSync(filePath, str)
  49. resolve1(str)
  50. }
  51. })
  52. })
  53. })
  54. )
  55. .then(() => resolve(files))
  56. .catch(err => reject(err))
  57. }
  58. )
  59. })
  60. }
  61. module.exports = install
  1. ...
  2. //记得加上bundledDependencies 打包的时候将以下的插件打包进入 或者将这些包写入dependencies 生成环境使用(推荐)
  3. "bundledDependencies": [
  4. "npmlog",
  5. "fs-extra",
  6. "glob",
  7. "ejs"
  8. ]
  1. ...
  2. //自定义安装
  3. async installCustomTemplate() {
  4. if (await this.pkg.exists()) {
  5. const rootFile = this.pkg.getRootFilePath()
  6. if (fs.existsSync(rootFile)) {
  7. const templatePath = path.resolve(this.pkg.cacheFilePath, 'template')
  8. const options = { templatePath, projectInfo: this.projectInfo, template: this.template }
  9. const code = `require('${rootFile}')(${JSON.stringify(options)})`
  10. const ret = await execAysnc('node', ['-e', code], {
  11. cwd: process.cwd(), //cwd 子进程的当前工作目录
  12. stdio: 'inherit' //inherit 将相应的stdio传给父进程或者从父进程传入,相当于process.stdin,process.stout和process.stderr
  13. })
  14. if (ret === 0) {
  15. log.success('命令执行成功')
  16. } else {
  17. throw new Error('命令执行成功失败')
  18. }
  19. }
  20. }
  21. }

image.png