引言
下面是用脚手架的初始化项目的例子。
当你想做一个脚手架的时候,看到这些可以选择的步骤,是不是无从下手,感觉快要被劝退了,其实你想要的东西都可以在npm
找得到,下面教大家创建一个简单的脚手架的流程,这里都用到的上层建筑(用的都是npm库,门槛低😊),附上我的仓库
第一步 创建项目
来看看目录结构
都2022年,不会还有人不用typescript
吧,用typescript
是有好处的,至少可以体验丰富的代码提示,core
是核心代码,通过rollup
进行打包,用pnpm
进行包管理,template
是需要用到的模版,eslint
管理代码格式
第二步 选项提示
像我们用vue-cli
的时候都会有那些选项提示,可以去配置不同的东西,那我们可以用到一个库prompts
,下面使用这个库的方式,删减了一点,具体可以去看我的仓库
// core/initOptions.ts
import prompts from 'prompts'
import type { PromptObject } from 'prompts'
interface result {
projectName?: string
hasProjectDir?: boolean
pickPresets?: string
}
const options: PromptObject[] = [
{
name: 'projectName',
type: 'text',
message: 'Project Name:',
initial: 'create-app'
},
{
name: 'pickPresets',
type: 'select',
message: '请选择一个预设',
choices: [
{ title: 'vue3 ', value: 'vue' },
{ title: 'react ', value: 'react' }
]
}
]
const initOptions = async () => {
try {
const result: result = await prompts(options,
{
onCancel: () => {
throw new Error('取消操作')
}
})
return result // 这里返回的是已经选好的 optios 对象
} catch (err: any) {
process.exit(1) // 退出进程 1 代表失败
}
}
export default initOptions
第三步 编写模版
我们先来简单的,这里新建一个template
存放我们的模版,根据上面选好的选项,去判断我们接下来要用哪个模版,我们来思考一下,怎么把文件夹复制到我们创建的文件夹呢,我们首先想到的是用fs
模块,去找这个文件夹有没有,有就进入里面去一步步遍历,如果自己想磨练node
api的话可以这么做,灵活性很高,如果不想那么麻烦,这里推荐一个fs-extra
,这个库可以把一整个文件夹都复制过去,这样我们的难度有降低了很多。
// core/execute.ts
import { green, bold } from 'kolorist'
import { removeSync, ensureDirSync, copySync } from 'fs-extra'
import { join, resolve, relative } from 'path'
import { result } from './type'
const cwd = process.cwd() // 获取node进程的当前工作目录
type template ='typescript-react' |'typescript-vue'
const templatePath = (...dir:template[]) => resolve(__dirname, '../template', ...dir)
const execute = (options:result) => {
const { projectName, pickPresets, hasProjectDir } = options
const root = join(cwd, projectName!)
if (hasProjectDir) {
removeSync(root)
} else {
ensureDirSync(root)
}
if (pickPresets === 'react') {
copySync(templatePath('typescript-react'), root)
}
if (pickPresets === 'vue') {
copySync(templatePath('typescript-vue'), root)
}
console.log('\nDone. Now run:\n')
if (root !== cwd) {
console.log(` ${bold(green(`cd ${relative(cwd, root)}`))}`)
}
console.log(` ${bold(green('pnpm install'))}\n\n`)
}
export default execute
当我们逻辑写完了,怎么去显示那个cd project
、pnpm install
这几个字,其实看上面这都是console.log
的产物,我们可以用kolorist
去变换颜色,然后用ts-node
执行index.ts
文件就能看出效果啦
第四步 npm link测试是否正常
发布npm
包之前,我们可以先在本地测试,首先要在package.josn
里面加bin
字段,用于运行这个脚本的指令,具体我也不是很清楚里面的原理,不过使用方法可以看这里
,mian
就指向你打包后的文件,具体配置看下面
{
"name": "swift-app",
"version": "1.0.3",
"description": "通过cli创建自定义模版",
"main": "/dist/index.js",
"bin": {
"swift-app": "dist/index.js"
}
}
还有一个要注意的就是打包生成的文件#!/usr/bin/env node
这段命令是会打包到模块里面的,到时候运行的时候就会报错,找不到可执行的命令,这个也很好解决
// rollup.config.js
export default {
input: 'core/index.ts',
output: {
dir: 'dist',
format: 'cjs',
banner: '#!/usr/bin/env node'
}
}
然后通过npm link
去做包链接,然后再执行bin
的名称就可以运行啦,没问题就发布到npm
就可以使用啦
遇到的问题
tsconfig配置
老实说,我也不懂ts
的配置,去官网找吧,又不是看得很明白,导致运行时一堆报错,然后我发现了文档已经有很多预设了,然后extends
用就好了,compilerOptions
就不用配了,运行后也没有报错了
rollup打包ts问题
之前第一版的时候用的是webpack
打包,之后觉得打包出来的文件格式不够美观,就换成了rollup
了,rollup
的配置也是超级简单,唯一遇到的问题就是下面的这种报错
于是查了查官网,发现
rollup
是不会解析你用到的依赖在哪,不会帮你引进来,不像webpack
一样会根据你用到的依赖一层一层进去找形成依赖图,下面是官网说的
所以现在要用到两个库
rollup-plugin-node-resolve
和rollup-plugin-commonjs
,这两个库已经被转移了,我们要在这基础上改改@rollup/plugin-node-resolve
和@rollup/plugin-commonjs
。
@rollup/plugin-node-resolve
是用来告诉 Rollup 如何查找外部模块
@rollup/plugin-commonjs
是用来将 CommonJS 模块转换为 ES6
最后
这算是给新手搭建一个简单的脚手架方式吧,不用借助任何第三方脚手架工具,像yeoman
这些,希望这个脚手架流程能对你们有帮助