likes
comments
collection
share

论前端如何优雅地实现脚手架(3)

作者站长头像
站长
· 阅读数 35

前言:听说不会做脚手架的前端不是好前端,本系列带你从0到1创建一个属于个人的脚手架,适合快速创建模板项目

这一章节你可以学习到:

  1. path 模块的一些路相关路径获取方法
  2. fs 模块对文件和文件夹的复制
  3. 相关文件夹和函数的命名方式

1、构建函数

通过第二大章节,我们已经成功采集到用户输入的相关信息,这个时候我们就可以将对应的模板进行生成了。

  1. src/contain 中创建 createProject 函数,同时创建参数类型

    export interface Choosed {
      projectName: string;		// 项目名
      framework: string;		// 采用框架
      variant: string;			// 二次选项
    }
    export function createProject(answer: Choosed) {
    }
    
  2. index.ts 中引入并使用

    import { getArgs } from "./util.js"
    import { createProject } from "./contain.js"
    import startQA from "./create-inquir.js"
    
    // 1) 获取参数
    const ARGUMENTS = getArgs()
    process.env.__CREATE_NAME__ = ARGUMENTS[0];
    
    // 2) 初始化项目
    async function init() {
      try {
        const ANSWERS = await startQA()
        createProject(ANSWERS as any)
      } catch (error) {
      }
    }
    init()
    

2、获取相关路径

  1. util.ts 创建一个工具函数,用户获取当前工作目录的路径与传参的合并路径,这个函数可以帮助我们拿到用户执行时所在的目录,方便获取模板的生成位置:

    // 获取当前工作目录的路径与传参的合并路径
    export const getPathFromExecRoot = (path: string = ".") => join(process.cwd(), path)
    
  2. createProject 中首先获取相关路径:

    • srcPath:需要 cpoy 的模板
    • commonPath:模板项目存储的位置
    • destPath:模板输出位置
    import { getPathFromExecRoot } from "./util.js"
    
    // ...
    export function createProject(answer: Choosed) {
      // 1 获取相关路径
      const { projectName, variant } = answer
      const srcPath = getPathFromRoot(`template/${variant}`)
      const commonPath = getPathFromRoot(`template/common`)
      const destPath = getPathFromExecRoot(projectName);
    }
    

3、构建复制文件夹函数

util.js 导出四个新的工具函数:

  1. copyFile:将一个文件从 A 复制到 B

    这里会判断传入的文件路径是文件夹还是文件,如果文件则直接复制,文件夹则调用下一个函数 copyDir

    export const copyFile = (src: string, dest: string) => fs.statSync(src).isDirectory() ? copyDir(src, dest) : fs.copyFileSync(src, dest)
    
  2. copyDir:将一个文件夹从 A 复制到 B

    export const copyDir = (srcDir: string, destDir: string, exclude?: string[]) => {
      // 1 创建目录
      fs.mkdirSync(destDir, { recursive: true })
      // 2 循环复制
      const dirs = fs.readdirSync(srcDir)
      // 3 循环目录
      for (let fileName of dirs) {
        if (exclude?.includes(fileName)) continue;
        const destFileName = fileName
        const srcFile = resolve(srcDir, fileName)
        const destFile = resolve(destDir, destFileName)
        copyFile(srcFile, destFile)
      }
    }
    
  3. createProject 中引入使用

    export function createProject(answer: Choosed) {
      // 1 获取相关路径
      const { projectName, variant } = answer
      const srcPath = getPathFromRoot(`template/${variant}`)
      const commonPath = getPathFromRoot(`template/common`)
      const destPath = getPathFromExecRoot(projectName);
      // 复制文件夹
      copyDir(commonPath, destPath)
      copyDir(srcPath, destPath)
      console.log("================================== 模板生成成功 ==================================");
    }
    

4、测试模板输出

随便找个空文件夹即可,输入命令:

test hello-world

选择完成后,模板出现即为成功:

论前端如何优雅地实现脚手架(3)

论前端如何优雅地实现脚手架(3)

5、总结

通过这一大章的学习,其实我们的脚手架已经基本完成,大家可以思考下剩余的问题:

  1. package.json 中的 name 属性如何变成我们设置的项目名?
  2. .gitignore 是否可以直接使用,会有什么问题,有没有更巧妙地方式去 copy?
  3. 结尾的完成提示是否可以更好看点?
  4. ...

这些问题,将会在下一章节中去解决,您可以自行思考或者解决下,敬请期待!

转载自:https://juejin.cn/post/7390447879406649355
评论
请登录