如何手动去搭建企业级脚手架 sca-create-app (二)

sca-create-app 创建项目文件

前言

上一篇文章 《如何手动去搭建企业级脚手架 sca-cli (一)》我们实现了sca-cli dev build的脚手架工具,用于项目的开发环境构建与线上环境下打包,基于Vue 2.x的框架,来实现项目的开发、构建,打包。
但是sca-cli只提供简单的项目打包与构建的工作,我们项目的文件创建还是需要我们自己手动去创建,因此本文我们需要提供 sca-create-app 这个脚手架工具去实现项目文件的搭建。

实现思路

简单思路

项目开发文件的创建,一般的想法:我们把自定义的项目文件传递到github上,然后我们通过下载到本地,然后加下配置文件,大致上的功能实现是这样的:

  1. commander 新增 init
  2. download-git-repo 传递github仓库地址,下载项目
  3. child_process 里面的spawn 功能,安装依赖 spawn(‘npm’, [‘install’], { cwd: ./${name} })
  4. open 打开页面 http://localhost:8080
  5. 使用 spawn(‘npm’, [‘run’,‘serve’], { cwd: ./${name} }) 启动页面
  6. 增加一些个性化的配置命令操作代码,比如新增页面文件或者新增路由文件配置,通过handlebars 编写模板文件,然后fs.writeFileSync 生成文件内容。

这样的流程,也是最简单的,很容易去实现。这样的实现方式没有任何问题,只是相对我个人觉得这样,后续不太好维护,也没有一个版本的概念。只能临时学习一些技术知识可以这样简单的搞一下。相对于企业级别的,这样越显得过于简单与简陋。

成熟思路

我们需要一个脚手架专门为项目创建负责,项目文件也需要有个版本号~项目创建的版本号与项目文件的版本号需要保持一致,这样我们才能保证项目开发版本的一致性。避免出现脚手架某最新版本新增了功能,但是项目文件的版本号是老的版本,会导致新增的功能无法使用。随着时间的版本迭代,势必会导致,现在老项目存在的问题:webpack 现在都已经 5.x , 而你的老项目里面还是使用 webpack 1.x / 2.x /3.x / 4.x等各色各项五花八门。

大致的实现功能思路如下:

  1. 引入 lerna 来对进行管理,发布,统一版本号,保障版本的一致性
  2. 创建两个 npm 包:(1)sca-create-app 项目安装脚手架 ,(2)@sca-cli/app-template-vue 项目文件
  3. 可以根据需求创建各种:(1)Vue 框架的 @sca-cli/app-template-vue 项目包(2)React 框架的 @sca-cli/app-template-react 项目包(3)Svelte 框架的 @sca-cli/app-template-svelte 项目包(4)Vue,React ,Svelte + Typescript 项目包… 等其他各种框架的项目包
  4. 实现脚手架命令行:npx sca-create-app new-dir --template @sca-cli/app-template-vue [ --target | --use-yarn | --use-npm | --no-install | --install | --cover
  5. 做一些个性化的配置与交互式的体验,按照各自需求做开发,做相应的版本控制。

这样的开发实践,我们做到了实现脚手架的功能开发与项目文件都是各自独立的,又紧密联系再一起。可以单独开发又可以一致统一版本号~ 项目开发与维护都很简单也便捷,体现了前端工程化体系的优势。

功能实现

sca-create-app 脚手架实现

package.json 初始化与配置

package.json 初始化:

npm init -y

package.json 修改如下:

"name": "sca-create-app",
  "version": "1.0.0",
  "description": "新建项目文件初始化工具",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "nathan",
  "license": "ISC",
  "bin": {
    "sca-create-app": "./index.js"
  },
  "homepage": "https://gitee.com/tootem9/sca-cl/tree/master/sca-create-app/cli#readme",
  "repository": {
    "type": "git",
    "url": "https://gitee.com/tootem9/sca-cl",
    "directory": "sca-create-app/cli"
  },
  "dependencies": {}

说明:

  • homepage 就是项目仓库的地址
  • repository 配置仓库的路径、地址、类型
  • bin 包的入口文件配置

安装依赖

npm install clear execa fs-extra kleur yargs-parser --save

依赖包说明:

  • clear 清除 bash/shell 页面上其他操作痕迹
  • execa bash/shell 命令行操作库,类似 child_process 里面的spawn 功能。
  • fs-extra, node 库 fs的扩展,主要用到 copy removeSync 方法
  • kleur 命令行代码显示库,类似chalk 库,也可以替换使用chalk
  • yargs-parser 读取 process.argv 里面的一系列命令,直接返回json 格式对象,方便。当前就只有一个命令行,没有交互式配置,估不考虑使用commander

代码实现

我们需要实现的功能主要是:

发布的功能命令:npx sca-create-app new-dir --template @sca-cli/app-template-vue [ --target | --use-yarn | --use-npm | --no-install | --install | --cover ]

本地开发命令:npx sca-create-app new-dir --template ./app-template-vue [ --target | --use-yarn | --use-npm | --no-install | --install | --cover ]

(1)解析命令代码:
const {template,useYarn, useNpm, toInstall, targetDirectoryRelative, targetDirectory} = validateArgs(
    process.argv,
);
(2)校验命令是否正确
if (useYarn && useNpm) {
    errorLog('不能同时使用 npm 和 yarn')
}
if (useYarn && !hasShellCommand('yarn')) {
    errorLog('yarn 没有安装过~ ')
}
if (useNpm && !hasShellCommand('npm')) {
    errorLog('npm 没有安装过~ ')
}
if (typeof template !== 'string') { 
    errorLog('--template 对应的模板文件丢失')
}
if (_.length > 3) {
    errorLog('命令行操作代码有误~请检查')
}

const targetDirectoryRelative = target || _[2];
const targetDirectory = path.resolve(process.cwd(), targetDirectoryRelative)
if (fs.existsSync(targetDirectory) && !cover) {
    errorLog(`${targetDirectory} 文件已经存在了,使用 \`--cover\` 覆盖这个目录`)
}
(3)创建目录与package.json 配置
//创建目录
  fs.mkdirSync(targetDirectory, { recursive: true });
   
   //创建package.json
   await fs.promises.writeFile(path.join(targetDirectory, 'package.json'), `{"name": "sca-vue-app"}`);
(4)安装模板
await execa('npm', ['install', template, '--ignore-scripts'], {
    cwd: targetDirectory,
    all: true,
});
(5)拷贝模板文件

拷贝模板文件的操作,实际上就是在你安装npm包的node_modules 里面找到你的模板,然后拷贝一份到你的当前目录下的操作

await copy(path.join(targetDirectory, 'node_modules', template), targetDirectory);
(5)初始化 package.json

为何要初始化模板文件呢?因为我们如果把我们的模板文件 npm publish 之后吗,npm 会再上传的模板文件的package.json里面添加 下划线 _ 为开头的一系列 npm 包的配置文件,这些对于我们自身的项目来说,是多余的,所以我们需要取出我们需要的scripts, dependencies,devDependencies ,name,author,license,description 等相关的。

const packageFile = path.join(dir, 'package.json')
//
removeSync(path.join(dir, 'package-lock.json'));
removeSync(path.join(dir, 'node_modules'));

const { scripts, dependencies, devDependencies } = require(packageFile)
const { test, dev, build, ...otherScripts } = scripts
const packjosnInfo = JSON.stringify({
        name: "sca-vue-app",
        author: "",
        license: "ISC",
        description:'sca-vue-app',
        scripts: { test, dev, build, ...otherScripts },
        dependencies,
        devDependencies
    },
    null,
    2,
)
await fs.promises.writeFile(packageFile, packjosnInfo)

await fs.promises.writeFile(
    path.join(dir, '.gitignore'),
    ['dist', 'node_modules'].join('\n')
)

初期我们项目安装初始化项目包的一些依赖,我们需要删除掉 package-lock.json node_modules ,使用 fs.promises.writeFile 来对文件做相应的写入操作

(6)个性化配置

新增了是否初始化 npm install 操作,我们根据配置

const npmInstallOptions = {
   cwd: targetDirectory,
   stdio: 'inherit',
};
execa('npm', ['install', '--loglevel', 'error'], npmInstallOptions);

这样基本上已经实现了我们想要的基本要求了。我们也可以在这里添加其他的个性化配置,或者其他的文件写入的要求,比如 eslint,babel,.prettierrc, post 等一些配置。这些额外的添加,只会让我们的项目文件更加的专业化,更加的完善,符合我们工程化体系架构的要求,这些后续再优化。

@sca-cli/app-template-vue 实现

新增文件与文件夹

@sca-cli/app-template-vue 这个项目只是一个文件模板包,不需要跟脚手架这样去配置,只需要新增相关项目文件与配置一下 package.json 文件即可。

简单目录文件如下:

├── public
│   ├── favicon-32x32.png
│   ├── favicon.ico
│   ├── index.html
│   └── logo.svg
├── src
│   ├── App.vue
│   └── main.js
├── README.md
├── package.json

按照目录我们分别创建相应的文件夹与文件

package.json 配置

package.json 配置主要的如下 :

"name": "@sca-cli/app-template-vue",
"version": "1.0.0",
"description": "sca-cli vue项目模板文件",
"keywords": [
 	"sca-template-vue"
],
"publishConfig": {
	 "access": "public"
},
"author": "nathan",
"license": "ISC",
"homepage": "https://gitee.com/tootem9/sca-cl/tree/master/sca-create-app/app-template-vue#readme",
"repository": {
 	"type": "git",
 	"url": "https://gitee.com/tootem9/sca-cl",
 	"directory": "sca-create-app/app-template-vue"
},

主要配置介绍:

  1. name 这个很重要,这个就是你发布到npm上的包名
  2. publishConfig 里面的配置 “access”: “public” ,这样编写的原因是 npm 里面 @sca-cli/XXX,@开头的配置是收费专属的,你要想发布这样的,必须要配置这个,且你需要到npm 上 Create a New Organization ,输入@sca-cli 然后选择Unlimited public packagesFree 去 Create 然后+ Add New Organization 上传这个项目文件包 或者把这个包之间 npm publish 上去这个文件就会自动归属下面了
  3. author, license ,homepage, repository 这些配置的完整性,这些信息会再npm包的介绍页面展示出来

README.md文件编写

编写一系列项目介绍,项目安装操作

总结

我们实现了项目初始化搭建的脚手架开发,也单独抽离了项目文件的配置,不用像vue-cli 这些脚手架都全部封装在一起,然后根据交互式的命令去选择更加个性化的配置,最后生成你需要的项目。当然从某方面将 vue-cli 自身的脚手架功能确实相当的完善与健壮,各方表现都很出色。而我们现在自己开发的脚手架比较单一,简单的,基础的项目开发配置工作而已。换一个角度来看,我们在实际开发项目的时候,我们往往就需要简单的一个基础架构配置的项目框架就可以了,比如vue的单页面框架,我们就是需要vuex,vue-router,axios/vue-resource 这些以及项目开发与打包就足够了,剩下的其他个性化的架构配置,都是根据实际需求开发去不断的叠加上去的。而基础架构文件的简单配置,对后续项目的扩展与兼容,也容易需求,起码项目可操作性比较便利。符合我们现在项目开发中的快速敏捷性开发流程体验,而高度集成的项目架构,从兼容性,可维护难度与可扩展性方面就比较稍微弱一些。对于新手来说,高度集成的项目上手能力确实需要一定时间的积累与学习。

sca-create-app脚手架的实现,也充分体现了我们在开发上最重要的思想,就是让程序功能极具插件化,高集合度与低耦合度,微细颗粒化等这些特性。一个或多个功能的实现其实就是由众多个小功能来集合并打造实现而成的,而这些小功能有是单独存在,也可以被其他功能复用的。相互之间即使独立的也是融合的。这样的实现思路与插件化的工程体系,给项目开发带来了众多的便利。更加符合我们当下的开发理念。

参考资料:

项目仓库地址
@sca-cli/app-template-vue
sca-create-app
webpack官网
babeljs官网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值