網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
React官方腳手架
- 以5.0.1版本為例
- 創(chuàng)建項(xiàng)目執(zhí)行過(guò)程
源碼解讀debug
創(chuàng)建項(xiàng)目create-react-app my-app
,前面/packages/create-react-app
源碼解讀,詳細(xì)可以從create-react-app之pacakage/create-react-app核心源碼解讀(一)
相當(dāng)于在packages/react-scripts
運(yùn)行命令:
yarn init
以下scripts/init.js
,代碼從上到下按需執(zhí)行解析
1. 進(jìn)入函數(shù)
const appPackage = require(path.join(appPath, 'package.json'));
-
debug
代碼如下:
- 接著執(zhí)行,
useyarn
返回false
,因?yàn)榍懊媸褂玫?code>npm安裝的依賴(lài) -
templateName
的值為cra-template
; -
templatePath
運(yùn)行值為'my-app/node_modules/cra-template'
; -
templateJsonPath
運(yùn)行值'my-app/node_modules/cra-template/template.json'
- 獲取
templateJson
讀取值為:
2. templatePackageToReplace
執(zhí)行返回false
3. 新建項(xiàng)目my-app
的package.json
中添加scripts
,具體源碼如下:
appPackage.scripts = Object.assign(
{
start: 'react-scripts start',
build: 'react-scripts build',
test: 'react-scripts test',
eject: 'react-scripts eject',
},
templateScripts
);
到這里是不是很眼熟,create-react-app
腳手架初始化的項(xiàng)目,package.json
中就是這樣
4. 設(shè)置 eslint config
appPackage.eslintConfig = {
extends: 'react-app',
};
5. 設(shè)置browers list
6. 異步寫(xiě)入package.json
fs.writeFileSync(
path.join(appPath, 'package.json'),
JSON.stringify(appPackage, null, 2) + os.EOL
);
執(zhí)行完成后,就去新建的項(xiàng)目my-app
下查看如下:
- 判斷是否存在
README.md
,返回false
8. 拷貝模版項(xiàng)目到新建項(xiàng)目目錄下
在create-react-app/packages
目錄下可以看到有cra-template
為初始化項(xiàng)目模版
-
templateDir
運(yùn)行值為'my-app/node_modules/cra-template/template'
-
appPath
運(yùn)行值為'/Users/coco/project/shiqiang/create-react-app/packages/my-app'
- 源碼執(zhí)行拷貝
const templateDir = path.join(templatePath, 'template');
if (fs.existsSync(templateDir)) {
fs.copySync(templateDir, appPath);
} else {
console.error(
`Could not locate supplied template: ${chalk.green(templateDir)}`
);
return;
}
運(yùn)行完,去my-app
下查看,此時(shí)的目錄如下:
不存在.gitignore
文件
9. 判斷是否存在.gitignore
源碼如下:
const gitignoreExists = fs.existsSync(path.join(appPath, '.gitignore'));
if (gitignoreExists) {
// Append if there's already a `.gitignore` file there
const data = fs.readFileSync(path.join(appPath, 'gitignore'));
fs.appendFileSync(path.join(appPath, '.gitignore'), data);
fs.unlinkSync(path.join(appPath, 'gitignore'));
} else {
// Rename gitignore after the fact to prevent npm from renaming it to .npmignore
// See: https://github.com/npm/npm/issues/1862
fs.moveSync(
path.join(appPath, 'gitignore'),
path.join(appPath, '.gitignore'),
[]
);
}
返回false
,于是進(jìn)入else
,運(yùn)行完成,新建項(xiàng)目gitignore
替換為.gitignore
10. 初始化git repo
源碼如下:
function tryGitInit() {
try {
execSync('git --version', { stdio: 'ignore' });
if (isInGitRepository() || isInMercurialRepository()) {
return false;
}
execSync('git init', { stdio: 'ignore' });
return true;
} catch (e) {
console.warn('Git repo not initialized', e);
return false;
}
}
-
yarn
ornpm
if (useYarn) {
command = 'yarnpkg';
remove = 'remove';
args = ['add'];
} else {
command = 'npm';
remove = 'uninstall';
args = [
'install',
'--no-audit', // https://github.com/facebook/create-react-app/issues/11174
'--save',
verbose && '--verbose',
].filter(e => e);
}
- 安裝其他模板依賴(lài)項(xiàng)(如果存在)
const dependenciesToInstall = Object.entries({
...templatePackage.dependencies,
...templatePackage.devDependencies,
});
if (dependenciesToInstall.length) {
args = args.concat(
dependenciesToInstall.map(([dependency, version]) => {
return `${dependency}@${version}`;
})
);
}
debug
數(shù)據(jù):
args
運(yùn)行數(shù)據(jù):
11. 判斷是否安裝react
- 源碼如下:
if ((!isReactInstalled(appPackage) || templateName) && args.length > 1) {
console.log();
console.log(`Installing template dependencies using ${command}...`);
const proc = spawn.sync(command, args, { stdio: 'inherit' });
if (proc.status !== 0) {
console.error(`\`${command} ${args.join(' ')}\` failed`);
return;
}
}
- 函數(shù)
isReactInstalled
function isReactInstalled(appPackage) {
const dependencies = appPackage.dependencies || {};
return (
typeof dependencies.react !== 'undefined' &&
typeof dependencies['react-dom'] !== 'undefined'
);
}
- 關(guān)鍵打印信息:
12. 子進(jìn)程執(zhí)行安裝命令
- 源碼如下:
const proc = spawn.sync(command, args, { stdio: 'inherit' });
- 控制臺(tái)運(yùn)行信息如下:
13. 執(zhí)行刪除,刪除node_modules
目錄下的cra-template
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-JsjGCYba-
14. 顯示最優(yōu)雅的 cd 方式
- 源碼如下:
let cdpath;
if (originalDirectory && path.join(originalDirectory, appName) === appPath) {
cdpath = appName;
} else {
cdpath = appPath;
}
運(yùn)行后cdpath
值為my-app
15. 成功信息提示打印
- 源碼如下:
const displayedCommand = useYarn ? 'yarn' : 'npm';
console.log();
console.log(`Success! Created ${appName} at ${appPath}`);
console.log('Inside that directory, you can run several commands:');
console.log();
console.log(chalk.cyan(` ${displayedCommand} start`));
console.log(' Starts the development server.');
console.log();
console.log(
chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}build`)
);
console.log(' Bundles the app into static files for production.');
console.log();
console.log(chalk.cyan(` ${displayedCommand} test`));
console.log(' Starts the test runner.');
console.log();
console.log(
chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}eject`)
);
console.log(
' Removes this tool and copies build dependencies, configuration files'
);
console.log(
' and scripts into the app directory. If you do this, you can’t go back!'
);
console.log();
console.log('We suggest that you begin by typing:');
console.log();
console.log(chalk.cyan(' cd'), cdpath);
console.log(` ${chalk.cyan(`${displayedCommand} start`)}`);
if (readmeExists) {
console.log();
console.log(
chalk.yellow(
'You had a `README.md` file, we renamed it to `README.old.md`'
)
);
}
console.log();
console.log('Happy hacking!');
- 控制臺(tái)打印信息如下:
至此,新建項(xiàng)目react-scripts
中的完成
原文鏈接:https://blog.csdn.net/gkf6104/article/details/125919523
相關(guān)推薦
- 2024-02-29 UNI-APP頁(yè)面跳轉(zhuǎn)時(shí)(uni.navigateTo),參數(shù)傳遞
- 2023-03-15 Android?Studio格式化(Format)代碼快捷鍵介紹_Android
- 2022-10-20 Python?BautifulSoup?節(jié)點(diǎn)信息_python
- 2022-05-19 gorm整合進(jìn)go-zero的實(shí)現(xiàn)方法_Golang
- 2022-06-02 C語(yǔ)言用棧模擬實(shí)現(xiàn)隊(duì)列問(wèn)題詳解_C 語(yǔ)言
- 2022-11-03 python的環(huán)境conda簡(jiǎn)介_(kāi)python
- 2022-02-28 el-dialog 的關(guān)閉事件執(zhí)行兩次
- 2022-12-12 flutter自定義InheritedProvider實(shí)現(xiàn)狀態(tài)管理詳解_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支