构建 react应用程序 (二)(react-scripts实现原理)
来源:互联网 发布:ios10优化设置 编辑:程序博客网 时间:2024/06/06 04:22
在前面讲到了使用create-react-app来创建项目,这节我们来分析下原理。
react-scripts有以下支持,都帮你配置好了:
React, JSX, ES6, and Flow syntax support.Language extras beyond ES6 like the object spread operator.Import CSS and image files directly from JavaScript.Autoprefixed CSS, so you don’t need -webkit or other prefixes.A build script to bundle JS, CSS, and images for production, with sourcemaps.A dev server that lints for common errors.
翻译就不翻译了,大概就是说es6、css依赖啊 图片依赖之类的都已经通过react-scripts配置好了。
其实babel-core,webpack,等等这些 你都没下载,配置。
这些活,react-scripts 都帮你做了。
在命令窗口输入的是npm start,而start调用的是
"start": "react-scripts start",
找到node_modules里面的react-scripts 插件。点开bin\react-scripts.js文件内容
'use strict';const spawn = require('react-dev-utils/crossSpawn');const script = process.argv[2];const args = process.argv.slice(3);switch (script) { case 'build': case 'eject': case 'start': case 'test': { const result = spawn.sync( 'node', [require.resolve('../scripts/' + script)].concat(args), { stdio: 'inherit' } ); if (result.signal) { if (result.signal === 'SIGKILL') { console.log( 'The build failed because the process exited too early. ' + 'This probably means the system ran out of memory or someone called ' + '`kill -9` on the process.' ); }
[require.resolve('../scripts/' + script)].concat(args),
从上面这话可以看出调用start时需要调用scripts/start.js,点开该文件:
// @remove-on-eject-end'use strict';// Do this as the first thing so that any code reading it knows the right env.process.env.BABEL_ENV = 'development';process.env.NODE_ENV = 'development';// Makes the script crash on unhandled rejections instead of silently// ignoring them. In the future, promise rejections that are not handled will// terminate the Node.js process with a non-zero exit code.process.on('unhandledRejection', err => { throw err;});// Ensure environment variables are read.require('../config/env');const fs = require('fs');const chalk = require('chalk');const webpack = require('webpack');//这里引入了webpackconst WebpackDevServer = require('webpack-dev-server');//这里引入了webpack-dev-serverconst clearConsole = require('react-dev-utils/clearConsole');const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');const { choosePort, createCompiler, prepareProxy, prepareUrls,} = require('react-dev-utils/WebpackDevServerUtils');const openBrowser = require('react-dev-utils/openBrowser');const paths = require('../config/paths');//文件处理的配置const config = require('../config/webpack.config.dev');//dev解析的相关配置const createDevServerConfig = require('../config/webpackDevServer.config');const useYarn = fs.existsSync(paths.yarnLockFile);const isInteractive = process.stdout.isTTY;// Warn and crash if required files are missingif (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { process.exit(1);}// Tools like Cloud9 rely on this.const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;//端口设置 这就是为什么 端口号 不是8080 而是 3000 的原因,在这里可以改成8080,重新npm run start 生效 const HOST = process.env.HOST || '0.0.0.0';// We attempt to use the default port but if it is busy, we offer the user to// run on a different port. `detect()` Promise resolves to the next free port.choosePort(HOST, DEFAULT_PORT) .then(port => { if (port == null) { // We have not found a port. return; } const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; const appName = require(paths.appPackageJson).name; const urls = prepareUrls(protocol, HOST, port); // Create a webpack compiler that is configured with custom messages. const compiler = createCompiler(webpack, config, appName, urls, useYarn); // Load proxy config const proxySetting = require(paths.appPackageJson).proxy; const proxyConfig = prepareProxy(proxySetting, paths.appPublic); // Serve webpack assets generated by the compiler over a web sever. const serverConfig = createDevServerConfig( proxyConfig, urls.lanUrlForConfig ); const devServer = new WebpackDevServer(compiler, serverConfig); // Launch WebpackDevServer. devServer.listen(port, HOST, err => { if (err) { return console.log(err); } if (isInteractive) { clearConsole(); } console.log(chalk.cyan('Starting the development server...\n')); openBrowser(urls.localUrlForBrowser); }); ['SIGINT', 'SIGTERM'].forEach(function(sig) { process.on(sig, function() { devServer.close(); process.exit(); }); }); }) .catch(err => { if (err && err.message) { console.log(err.message); } process.exit(1); });
点开path路径,其实里面好多默认的配置都是写在该文件,可以通过修改改文件来实现自己文件的存放配置
// @remove-on-eject-begin */// @remove-on-eject-end'use strict';const path = require('path');const fs = require('fs');const url = require('url');// Make sure any symlinks in the project folder are resolved:// https://github.com/facebookincubator/create-react-app/issues/637const appDirectory = fs.realpathSync(process.cwd());const resolveApp = relativePath => path.resolve(appDirectory, relativePath);const envPublicUrl = process.env.PUBLIC_URL;function ensureSlash(path, needsSlash) { const hasSlash = path.endsWith('/'); if (hasSlash && !needsSlash) { return path.substr(path, path.length - 1); } else if (!hasSlash && needsSlash) { return `${path}/`; } else { return path; }}const getPublicUrl = appPackageJson => envPublicUrl || require(appPackageJson).homepage;function getServedPath(appPackageJson) { const publicUrl = getPublicUrl(appPackageJson); const servedUrl = envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/'); return ensureSlash(servedUrl, true);}// config after eject: we're in ./config/module.exports = { dotenv: resolveApp('.env'), appBuild: resolveApp('build'), appPublic: resolveApp('public'), appHtml: resolveApp('public/index.html'), appIndexJs: resolveApp('src/index.js'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), yarnLockFile: resolveApp('yarn.lock'), testsSetup: resolveApp('src/setupTests.js'), appNodeModules: resolveApp('node_modules'), publicUrl: getPublicUrl(resolveApp('package.json')), servedPath: getServedPath(resolveApp('package.json')),};// @remove-on-eject-beginconst resolveOwn = relativePath => path.resolve(__dirname, '..', relativePath);// config before eject: we're in ./node_modules/react-scripts/config/module.exports = { dotenv: resolveApp('.env'), appPath: resolveApp('.'), appBuild: resolveApp('build'), appPublic: resolveApp('public'), appHtml: resolveApp('public/index.html'), appIndexJs: resolveApp('src/index.js'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), yarnLockFile: resolveApp('yarn.lock'), testsSetup: resolveApp('src/setupTests.js'), appNodeModules: resolveApp('node_modules'), publicUrl: getPublicUrl(resolveApp('package.json')), servedPath: getServedPath(resolveApp('package.json')), // These properties only exist before ejecting: ownPath: resolveOwn('.'), ownNodeModules: resolveOwn('node_modules'), // This is empty on npm 3};const ownPackageJson = require('../package.json');const reactScriptsPath = resolveApp(`node_modules/${ownPackageJson.name}`);const reactScriptsLinked = fs.existsSync(reactScriptsPath) && fs.lstatSync(reactScriptsPath).isSymbolicLink();// config before publish: we're in ./packages/react-scripts/config/if ( !reactScriptsLinked && __dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1) { module.exports = { dotenv: resolveOwn('template/.env'), appPath: resolveApp('.'), appBuild: resolveOwn('../../build'), appPublic: resolveOwn('template/public'), appHtml: resolveOwn('template/public/index.html'), appIndexJs: resolveOwn('template/src/index.js'), appPackageJson: resolveOwn('package.json'), appSrc: resolveOwn('template/src'), yarnLockFile: resolveOwn('template/yarn.lock'), testsSetup: resolveOwn('template/src/setupTests.js'), appNodeModules: resolveOwn('node_modules'), publicUrl: getPublicUrl(resolveOwn('package.json')), servedPath: getServedPath(resolveOwn('package.json')), // These properties only exist before ejecting: ownPath: resolveOwn('.'), ownNodeModules: resolveOwn('node_modules'), };}// @remove-on-eject-end
点开webpack.config.dev.js,也会发现大量是曾相识的代码:
{ test: /\.(js|jsx)$/, enforce: 'pre', use: [ { options: { formatter: eslintFormatter, // @remove-on-eject-begin baseConfig: { extends: [require.resolve('eslint-config-react-app')], }, ignore: false, useEslintrc: false, // @remove-on-eject-end }, loader: require.resolve('eslint-loader'), }, ], include: paths.appSrc, }, // ** ADDING/UPDATING LOADERS ** // The "file" loader handles all assets unless explicitly excluded. // The `exclude` list *must* be updated with every change to loader extensions. // When adding a new loader, you must add its `test` // as a new entry in the `exclude` list for "file" loader. // "file" loader makes sure those assets get served by WebpackDevServer. // When you `import` an asset, you get its (virtual) filename. // In production, they would get copied to the `build` folder. { exclude: [ /\.html$/, /\.(js|jsx)$/, /\.css$/, /\.json$/, /\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, ], loader: require.resolve('file-loader'), options: { name: 'static/media/[name].[hash:8].[ext]', }, }, // "url" loader works like "file" loader except that it embeds assets // smaller than specified limit in bytes as data URLs to avoid requests. // A missing `test` is equivalent to a match. { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], loader: require.resolve('url-loader'), options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]', }, }, // Process JS with Babel. { test: /\.(js|jsx)$/, include: paths.appSrc, loader: require.resolve('babel-loader'), options: { // @remove-on-eject-begin babelrc: false, presets: [require.resolve('babel-preset-react-app')], // @remove-on-eject-end // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true, }, },
具体这些内容细节就不讲解了,说白点的我们以前通过手配置的webpack.config.js的内容react-scripts都已经帮我们做了,当然是否还缺其他组件,目前不知道在后续使用过程中,如果发现的不同我们再来一一记录。
阅读全文
0 0
- 构建 react应用程序 (二)(react-scripts实现原理)
- 使用 create-react-app 构建 react应用程序 (react-scripts)
- 使用 create-react-app 构建 react应用程序 (react-scripts)
- 使用 create-react-app 构建 react应用程序 (react-scripts)
- create-react-app 构建 react应用程序 (一)(react-scripts)
- 使用creat-react-app构建react程序(react-scripts)
- React(二)原理
- dva构建react应用程序
- 浅谈React实现评论框(二)
- react学习总结6--构建工具Gulp、Browserify(二)
- React(10)--构建工具
- React入门教程(二)
- React入门教程(二)
- react入门(二)
- React(二)
- React 学习 (二)
- react知识点(二)
- React(二):React开发神器Webpack
- 华为机试:字符个数统计、提取不重复的整数
- C语言基础笔记3
- 基于linux下的xshell脚本文件入门及例题
- htmlunit介绍
- PHP 命名空间
- 构建 react应用程序 (二)(react-scripts实现原理)
- Microsoft Office Picture Manager打开慢
- AJAX与JSON的一些总结(一)
- Spring+Quartz实现定时任务的配置方法
- 堆和栈的区别(转过无数次的文章)
- JAVA部分关键字分析
- Bitmap_关于图片压缩(1)
- Go编程基础—结构(struct)
- 解析C语言结构体,位段