前言
我之前好多次都是一步一步的安装eslint和prettier及相关依赖,一个配置文件一个配置文件的粘贴复制,并修改其中的相关配置。而且可能会在每个项目中都要去处理,如果项目工程规划化以后,eslint和prettier确实是项目少不了的配置。不知道你有没有像我一样操作过呢?
那么有没有一种更简单的方式去处理呢?答案是我终于遇到了。通过若川大佬的[源码共读活动] 发现了,真的是太棒了。
本文以vite脚手架
创建的项目为基础进行研究的,如果是其他脚手架创建的项目,那么就要自己去修改处理,但是原理是一样的。
那么接下来,我就要来一探究竟,先看看如何使用,然后查阅一下它的源码,看看它到底是如何实现的呢?
yarn create vite
一顿操作以后项目就创建完毕了
image.png
yarn
yarn dev
yarn create vite-pretty-lint
先来看没有执行命令前的文件目录
image.png
再来看执行完命令后的文件目录
image.png
可以发现文件目录中增加了eslint和prettier的相关配置,package.json中增加了相关的依赖、以及vite.config.xx文件也增加了相关配置,具体的文件变更可以查看https://github.com/lxchuan12/vite-project/commit/6cb274fded66634191532b2460dbde7e29836d2e。
一个命令干了这么多事情,真的太优秀了。接下来我们就去看看这如此优秀的源代码吧
通过大致的查看源代码,简单总结出来的代码执行过程示意图,仅供参考
未命名文件 (3).png
通过package.json
中的bin节点可以发现,yarn create vite-pretty-lint
最终执行的便是lib/main.js中的代码
"bin": {
"create-vite-pretty-lint": "lib/main.js"
},
因为我们现在只是要执行lib/main.js
这个入口文件,通过package.json
的scripts
也没有发现执行命令,所以现在我们可以直接通过node
来运行代码
node lib/main.js
调试成功的结果如下图所示
企业微信截图_16564645675849.png
npm i chalk
import chalk from 'chalk'
const log = console.log
// 字体背景颜色设置
log(chalk.bgGreen('chalk打印设置') )
// 字体颜色设置
log(chalk.blue('Hello') + ' World' + chalk.red('!'))
// 自定义颜色
const custom = chalk.hex('#F03A17')
const bgCustom = chalk.bgHex('#FFFFFF')
log(custom('customer'))
log(bgCustom('bgCustom'))
执行效果如下图所示
image.png
// 安装
npm i gradient-string
// 引入
import gradient from 'gradient-string'
// 使用
console.log(gradient('cyan', 'pink')('你好啊赛利亚欢迎来到编码世界'));
console.log(gradient('cyan', 'pink')('你好啊赛利亚欢迎来到编码世界'));
console.log(gradient('cyan', 'pink')('你好啊赛利亚欢迎来到编码世界'));
console.log(gradient('cyan', 'pink')('你好啊赛利亚欢迎来到编码世界'));
console.log(gradient('cyan', 'pink')('你好啊赛利亚欢迎来到编码世界'));
执行效果如下图所示
image.png
child_process node.js中的子进程。
在node.js中,只有一个线程执行所有的操作,如果某个操作需要大量消耗CPU资源的话,后续的操作就需要等待。后来node.js就提供了一个
child_process
模块,通过它可以开启多个子进程,在多个子进程之间可以共享内存空间,可以通过子进程的互相通信来实现信息的交换。
import { exec } from 'child_process';
exec('ls',(error, stdout,stderr)=> {
if(error) {
console.log(error)
return;
}
console.log('stdout: ' + stdout)
console.log('执行其他操作')
})
执行效果如下图所示
image.png
import fs from 'fs'
// 同步的读取方法,用来读取指定文件中的内容
fs.readFileSync()
// 同步的写入方法,用来向指定文件中写内容
fs.writeFileSync()
import path from 'path';
// 拼接路径
console.log(path.join('src', 'task.js')); // src/task.js
// 安装
npm i nanospinner
// 引入模块
import { createSpinner } from 'nanospinner';
const spinner = createSpinner('Run test').start()
setTimeout(() => {
spinner.success()
}, 1000)
执行效果如下图所示(Run test在加载的一个效果)
3.gif
交互式询问CLI 简单说就是交互式询问用户输入
npm i enquirer
import enquirer from 'enquirer'
let tempArray = ['major(1.0.0)','minor(0.1.0)', 'patch(0.0.4)', "customer" ]
const { release } = await enquirer.prompt({
type: 'select',
name: 'release',
message: 'Select release type',
choices: tempArray
})
if(release === 'customer') {
console.log(release, 'customer')
} else {
const targetVersion = release.match(/\((.*)\)/)[1]
console.log(targetVersion, 'targetVersion')
}
执行效果如下图所示:先出来一个下拉选择,选择完后根据if判断进行输出
4.gif
async function run() {
// 所有的逻辑代码
}
run().catch((e) => {
console.error(e);
});
通过run
函数封装异步方法,这样最外面调用run
函数时可以通过异步方法的catch
捕获错误异常。
看一个小例子
const runTest = async () => {
console.log('Running test')
throw new Error('run test报错了')
}
runTest().catch(err => {
console.log('Error: ' + err)
})
执行后打印顺序如下
Running test
Error: Error: run test报错了
可以发现catch中截获了异常
接下来开始进入run函数了
// 这个看上面的引入模块解析即可
console.log(
chalk.bold(
gradient.morning('\n Welcome to Eslint & Prettier Setup for Vite!\n')
)
);
export function getOptions() {
const OPTIONS = [];
fs.readdirSync(path.join(__dirname, 'templates')).forEach((template) => {
const { name } = path.parse(path.join(__dirname, 'templates', template));
OPTIONS.push(name);
});
return OPTIONS;
}
export function askForProjectType() {
return enquirer.prompt([
{
type: 'select',
name: 'projectType',
message: 'What type of project do you have?',
choices: getOptions(),
},
{
type: 'select',
name: 'packageManager',
message: 'What package manager do you use?',
choices: ['npm', 'yarn'],
},
]);
}
try {
const answers = await askForProjectType();
projectType = answers.projectType;
packageManager = answers.packageManager;
} catch (error) {
console.log(chalk.blue('\n Goodbye!'));
return;
}
getOptions
函数根据fs.readdirSync
读取项目工程template
文件夹下的所有文件,并通过path.parse
转换对象,来获取文件名称name
。
askForProjectType
函数通过enquirer.prompt
返回两个交互式命令行,供用户进行选择projectType
选择项目类型:【react-ts】 【react】【vue-ts】 【vue】packageManager
选择项目包管理方式:【npm】 【yarn】
假如我们上面选择的是[vue-ts]
const { packages, eslintOverrides } = await import(
`./templates/${projectType}.js`
);
/template/vue-ts.js
模板中的代码(其中代码较多但一看就明白我就不贴了),就是export
导出了两个固定的模板变量数组,packages
则相当于要引入的npm模块列表,eslintOverrides这算是.eslintrc.json
初始化模板。
const packageList = [...commonPackages, ...packages];
const eslintConfigOverrides = [...eslintConfig.overrides, ...eslintOverrides];
const eslint = { ...eslintConfig, overrides: eslintConfigOverrides };
commonPackages
是shared.js
中预定义的公共的npm 模块eslint
则是通过公共npm模块中的eslintConfig
和上面选择的template/xxxx.js
中的进行拼接组成。
const commandMap = {
npm: `npm install --save-dev ${packageList.join(' ')}`,
yarn: `yarn add --dev ${packageList.join(' ')}`,
};
将packageList
数组通过join转换为字符串,通过命令将所有拼接npm模块一起安装
image.png
const projectDirectory = process.cwd();
const viteJs = path.join(projectDirectory, 'vite.config.js');
const viteTs = path.join(projectDirectory, 'vite.config.ts');
const viteMap = {
vue: viteJs,
react: viteJs,
'vue-ts': viteTs,
'react-ts': viteTs,
};
const viteFile = viteMap[projectType];
const viteConfig = viteEslint(fs.readFileSync(viteFile, 'utf8'));
const installCommand = commandMap[packageManager];
if (!installCommand) {
console.log(chalk.red('\n✖ Sorry, we only support npm and yarn!'));
return;
}
根据选择的项目类型,来拼接vite.config的路径,并读取项目中的vite.config配置文件
上面用到了一个函数viteEslint
,这个具体的实现可以去看shared.js
中,主要就是读取文件内容后,传入的参数code,就是vite.config.ts
中的所有字符
通过babel的parseSync
转换为ast。ast对象如下图所示
1656558646620.png
对ast数据进行了一系列的处理后,再通过babel
的transformFromAstSync
将ast转换为代码字符串。
对于babel处理这一块我也不太了解,有时间我得去加一下餐,具体的可以参考 https://juejin.cn/post/6844904008679686152
const spinner = createSpinner('Installing packages...').start();
exec(`${commandMap[packageManager]}`, { cwd: projectDirectory }, (error) => {
if (error) {
spinner.error({
text: chalk.bold.red('Failed to install packages!'),
mark: '✖',
});
console.error(error);
return;
}
const eslintFile = path.join(projectDirectory, '.eslintrc.json');
const prettierFile = path.join(projectDirectory, '.prettierrc.json');
const eslintIgnoreFile = path.join(projectDirectory, '.eslintignore');
fs.writeFileSync(eslintFile, JSON.stringify(eslint, null, 2));
fs.writeFileSync(prettierFile, JSON.stringify(prettierConfig, null, 2));
fs.writeFileSync(eslintIgnoreFile, eslintIgnore.join('\n'));
fs.writeFileSync(viteFile, viteConfig);
spinner.success({ text: chalk.bold.green('All done! '), mark: '✔' });
console.log(
chalk.bold.cyan('\n Reload your editor to activate the settings!')
);
});
首先通过createSpinner
来创建一个命令行中的加载,然后通过child_process
中的exec
来执行[3.4.6]
中生成的命令,去安装依赖并进行等待。
如果命令执行成功,则通过fs.writeFileSync
将生成的数据写入到三个文件当中.eslintrc.json
、.prettierrc.json
、.eslintignore
、vite.config.xx
。
印象里面大家可能对它的记忆可能都停留在,npm init
之后是快速的初始化package.json
,并通过交互式的命令行让我们输入需要的字段值,当然如果想直接使用默认值,也可以使用npm init -y
。
create-app-react
创建项目命令,官网链接可以直接查看 https://create-react-app.dev/docs/getting-started
//官网的三种命令
npx create-react-app my-app
npm init react-app my-app
yarn create react-app my-app
//我又发现npm create也是可以的
npm create react-app my-app
上述这些命令最终效果都是可以执行创建项目的
同样的vite
创建项目的命令
//官网的命令
npm create vite@latest
yarn create vite
pnpm create vite
// 指定具体模板的
// npm 6.x
npm create vite@latest my-vue-app --template vue
//npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue
yarn create vite my-vue-app --template vue
pnpm create vite my-vue-app --template vue
可以发现vite
官网没有使用npx
命令,不过我在我自己电脑上尝试了另外几个命令确实也是可以的
npx create-vite my-app
npm init vite my-app
image.png
通过上面的对比可以一个小问题,yarn create
去官网查了是存在这个指令的,官网地址可看 https://classic.yarnpkg.com/en/docs/cli/create#search
而对于npm create
这个命令在npm官网是看不到的,但是在一篇博客中发现了更新日志
image.png
意思就是说npm create xxx
和npm init xxx
以及yarn create xxx
效果是一致的。那么我们来本文的命令行
// 我们是通过npm安装的,并且包名里是包含create的
npm i create-vite-pretty-lint
// 那么以下几种方式都可以使用的
npm init vite-pretty-lint
npm create vite-pretty-lint
yarn create vite-pretty-lint
npx create-vite-pretty-lint
再来看一下npx
假如我们只在项目中安装了vite
,那么node_modules
中.bin
文件夹下是会存在vite
指令的
image.png
如果我们想在该项目下执行该命令第一种方式便是
image.png
第二种方式就是直接在package.json的scripts属性下
image.png
关于npx的详细说明可以看一下阮一峰大佬的精彩分享 http://www.ruanyifeng.com/blog/2019/02/npx.html
有兴趣的话可以看看我前几天刚刚总结的关于V8引擎是如何运行JavaScript代码的,其中就涉及到关于AST的部分https://juejin.cn/post/7109410330295402509。
接下来有时间我会简单的把AST详细的学习一下,查了很多资料发现AST还是非常重要的,无论是babel、webpack、vite、vue、react、typescript等都使用到了AST。
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/C9js52qY1W8faE3GP1KVZw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。