文章目录
前言
学习来源:尚硅谷bilibili课程
这个课程收藏了很久了,但是一直都没有开始看,现在一边学习一边记录笔记希望可以督促自己。
本节是一个粗略的概览
从package.json开始
scripts
react-creact-app运行结束后,package.json的script中有四个启动指令
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
他们分别是
- 开发环境指令
- 生产环境指令
- 测试指令
-
eject 默认配置在react-scripts的包里面里面,eject 负责将react-scripts里面的配置打包到外面,运行后就会在外面暴露两个目录(config/scripts),我们就可以修改它。这是一个不可逆的指令,在暴露出来之后同时会下载一些相应的依赖包
browserslist
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
browerslist是浏览器列表,指的是样式的兼容性做到什么程度,一个是生产环境production,一个是development是开发环境
- production 支持市面上99.8%的浏览器,不要死了的和淘汰的浏览器
- development 主要是为了方便开发看到效果,所以会少一点
config - eject之后暴露出来的路径
paths.js
path模块是用来处理路径的
// 引入模块
const path = require('path');
const fs = require('fs');
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
// 创建了一个变量叫appDirectory,项目根目录
const appDirectory = fs.realpathSync(process.cwd());
// 生成绝对路径的方法
// 接受一个相对路径,返回一个绝对路径,绝对路径是基于根目录产生的绝对路径
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
// 所有资源的公共访问路径
// 接下来又调用了一个调度方法 getPublicUrlOrPath,获取public的url
const publicUrlOrPath = getPublicUrlOrPath(
process.env.NODE_ENV === 'development',
// 去package.json看有没有homepage,如果有就是用homepage开头
require(resolveApp('package.json')).homepage,
// 或者从环境变量中找PUBLIC_URL
process.env.PUBLIC_URL
// 如果都没有的话,默认值就是/
);
// 解析模块的方法
const resolveModule = (resolveFn, filePath) => {
// moduleFileExtensions是文件扩展名的数组
// 拿到文件扩展名,查看文件路径是否符合文件扩展名的规则
const extension = moduleFileExtensions.find(extension =>
fs.existsSync(resolveFn(`${filePath}.${extension}`))
);
// 存在就解析它
if (extension) {
return resolveFn(`${filePath}.${extension}`);
}
return resolveFn(`${filePath}.js`);
};
// 暴露出去的路径
module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
appBuild: resolveApp(buildPath),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
appPackageJson: resolveApp('package.json'),
...
}
- appDirectory就是app的一个文件夹,他对应的目录是我们输入的指令的目录,也就是项目的根目录
- getPublicUrlOrPath 获取public的url,也就是所有公共资源的访问路径
scripts - eject之后暴露出来的路径
start.js
// 开发环境,定义环境变量
process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';
// 捕获异常,如果有异常就报错
process.on('unhandledRejection', err => {
throw err;
});
// 加载一些环境变量
require('../config/env');
// 判断是否使用了yarn
const useYarn = fs.existsSync(paths.yarnLockFile);
// 判断必要文件是否存在(public/index.html src/index.js),如果不存在就退出进程
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
}
// 定义默认端口号和域名
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const HOST = process.env.HOST || '0.0.0.0';
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
// 检查浏览器
checkBrowsers(paths.appPath, isInteractive)
.then(() => {
// 成功之后会检查端口号,3000被占用就会自动+1再去检查
// 选择相应的端口号
return choosePort(HOST, DEFAULT_PORT);
})
// 端口号
.then(port => {
if (port == null) {
return;
}
// 调用configFactory方法生成webpack的配置,生成的是开发环境的配置
const config = configFactory('development');
// 协议
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
// app名称
const appName = require(paths.appPackageJson).name;
...
// 创建编译器
const compiler = createCompiler({
appName,
config,
devSocket,
urls,
useYarn,
useTypeScript,
tscCompileOnError,
webpack,
});
// 创建代理,去appPackageJson中去找proxy的配置,所以我们可以直接在package.json中去写proxy
const proxySetting = require(paths.appPackageJson).proxy;
const proxyConfig = prepareProxy(
proxySetting,
paths.appPublic,
paths.publicUrlOrPath
);
// 创建devServer配置,开发服务器
const serverConfig = createDevServerConfig(
proxyConfig,
urls.lanUrlForConfig
);
const devServer = new WebpackDevServer(compiler, serverConfig);
// 启动服务
devServer.listen( ...
);
})
start.js的文件逻辑
- 首先检查当前是否有必要核心文件,入口文件
- 检查浏览器
- 检查端口号
- 创建编译器
- 加载proxy配置
- 准备devServer配置
- 生成devServer
- 启动服务