React Typescript音乐播放器项目笔记:4、create-react-app搭建代理(一)

19 篇文章 0 订阅
17 篇文章 0 订阅

项目地址https://github.com/BUPTlhuanyu/react-music-lhy

create-react-app搭建代理(一)

经过npm run eject之后配置代理,create-react-app用的是webpack-dev-server实现一个简单的web服务器,webpack-dev-server是基于express实现的。webpack-dev-server相关配置可参考webpack中devServer

create-react-app配置初探

首先贴出项目的启动相关的代码:

然后贴出package.json文件的代码如下,这里并不想用webpack-dev-server中的proxy字段进行代理转发,所以package.json文件中也看不到proxy字段(这里在下一篇文章会实现利用这个字段以及用expres搭建一个代理转发服务器)。

{
  "name": "react-music-lhy",
  "version": "0.1.0",
  "private": true,
  "dependencies":{...}
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js"
  },
  "eslintConfig":{...}
  "browserslist":{...}
  "jest":{...}
  "babel":{...}
  "devDependencies":{...}
}

执行npm start启动项目,执行start.js,代码如下:

'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.
//通过监听unhandledrejection事件,promise被reject了但是没有reject处理函数时,该事件被触发。
// The unhandledrejection event is fired
// when a JavaScript Promise is rejected
// but there is no rejection handler to deal with the rejection.
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');
const WebpackDevServer = require('webpack-dev-server');
const 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');
//用于生成不同模式下的config
const configFactory = require('../config/webpack.config');
//webpack-dev-server的配置
const createDevServerConfig = require('../config/webpackDevServer.config');

const useYarn = fs.existsSync(paths.yarnLockFile);
const isInteractive = process.stdout.isTTY;

// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
  process.exit(1);
}

// Tools like Cloud9 rely on this.
//webpack-dev-server监听的端口,默认为3000端口,访问url为localhost:3000的时候会被webpack-dev-server服务器代理并返回html页面
//host默认为'0.0.0.0'也就是localhost
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const HOST = process.env.HOST || '0.0.0.0';

if (process.env.HOST) {...}

// We require that you explictly set browsers and do not fall back to
// browserslist defaults.
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
checkBrowsers(paths.appPath, isInteractive)
  .then(() => {
    // We attempt to use the default port but if it is busy, we offer the user to
    // run on a different port. `choosePort()` Promise resolves to the next free port.
    return choosePort(HOST, DEFAULT_PORT);
  })
  .then(port => {
    if (port == null) {
      // We have not found a port.
      return;
    }
	//生成开发环境下的config
    const config = configFactory('development');
    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.
	//利用配置进行编译,webpack(config)的封装
    const compiler = createCompiler(webpack, config, appName, urls, useYarn);

    // Load proxy config
      //没有配置packjson的时候proxyConfig为undefined
    const proxySetting = require(paths.appPackageJson).proxy;
    const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
    // Serve webpack assets generated by the compiler over a web server.
    //urls.lanUrlForConfig是根据协议,host以及端口生成的,这里为本机的ip地址
    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'));
        console.log(chalk.cyan(urls.lanUrlForConfig))
	  //打开浏览器,默认为localhost
      openBrowser(urls.localUrlForBrowser);
    });

	['SIGINT', 'SIGTERM'].forEach(...);
  })
  .catch(err => {
    if (err && err.message) {
      console.log(err.message);
    }
    process.exit(1);
  });

start.js根据如下代码导入webpackDevServer.config对webpack-dev-server创建的服务器进行自定义配置:

	const createDevServerConfig = require('../config/webpackDevServer.config');
    const serverConfig = createDevServerConfig(
      proxyConfig,
      urls.lanUrlForConfig
    );

搭建简易代理

webpackDevServer.config.js的代码如下:

'use strict';

const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const ignoredFiles = require('react-dev-utils/ignoredFiles');
const paths = require('./paths');
const fs = require('fs');

const appRoute = require('../server/server.js')

const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const host = process.env.HOST || '0.0.0.0';

module.exports = function(proxy, allowedHost) {
  return {
    disableHostCheck:
      !proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
    // Enable gzip compression of generated files.
    compress: true,
    // 去掉WebpackDevServer's日志,但是会显示编译错误以及警告
    clientLogLevel: 'none',
    //告诉服务器从哪个目录中提供内容。只有在你想要提供静态文件时才需要。devServer.publicPath 将用于确定应该从哪里提供 bundle,并且此选项优先。
    contentBase: paths.appPublic,
    // By default files from `contentBase` will not trigger a page reload.
    watchContentBase: true,
	//模块热更新,css有效,js等其他的需要自己利用loder配置
    hot: true,
    //假设服务器运行在 http://localhost:8080 并且 output.filename 被设置为 bundle.js。默认 publicPath 是 "/",所以你的包(bundle)可以通过 http://localhost:8080/bundle.js 访问。publicPath: '/assets/',可以通过 http://localhost:8080/assets/bundle.js 访问 bundle。
    publicPath: '/',
    // 不打印打包过程
    quiet: true,
    watchOptions: {
      ignored: ignoredFiles(paths.appSrc),
    },
    // Enable HTTPS if the HTTPS environment variable is set to 'true'
    https: protocol === 'https',
    host,
    overlay: false,
    historyApiFallback: {
      // Paths with dots should still use the history fallback.
      // See https://github.com/facebook/create-react-app/issues/387.
      disableDotRule: true,
    },
    //  结合nginx的时候需要配置
    public: allowedHost,
    proxy,
    before(app, server) {
	  //src下没建立setupProxy,因此此处没用
      if (fs.existsSync(paths.proxySetup)) {
        // This registers user provided middleware for proxy reasons
        require(paths.proxySetup)(app);
      }
      // appRoute(app)
      // This lets us fetch source contents from webpack for the error overlay
      app.use(evalSourceMapMiddleware(server));
      // This lets us open files from the runtime error overlay.
      app.use(errorOverlayMiddleware());
      // This service worker file is effectively a 'no-op' that will reset any
      // previous service worker registered for the same host:port combination.
      // We do this in development to avoid hitting the production cache if
      // it used the same host and port.
      // https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
      app.use(noopServiceWorkerMiddleware());
    },
  };
};

这里介绍一种简单的代理,注意上面代码中有如下代码:

const appRoute = require('../server/server.js')
before(app, server) {
	...
  appRoute(app)
	...
}};

devServer.before的作用:在服务内部的所有其他中间件之前, 提供执行自定义中间件的功能。 这可以用来配置自定义处理程序

由于webpack-dev-server是基于express实现的,会执行devServer.before(app),其中appwebpack-dev-server利用express创建的web服务器对象,因此可以在这个函数中为app这个服务器增加自定义的路由。整个请求的逻辑就是:

在浏览器中输入http://localhost:3000/——>webpack-dev-server创建的服务器监听到3000端口的请求返回index.html文件以及boundle.js——>操作页面执行boundle.js中的代码向http://localhost:3000/api/getSomthing发出请求——>webpack-dev-server创建的服务器监听到3000端口的请求,根据开发者定义的路由向本地数据库或者远端服务器请求数据并返回。

api请求的顺序就是:http://localhost:3000收到的请求被代理到webpack-dev-server创建的服务器,webpack-dev-server服务器向远端服务器请求数据,然后数据由webpack-dev-server返回给http://localhost:3000最终展示在页面上。

这里在server目录下server.js文件中写如下代码:

const express = require('express')
const opn = require('opn')
const path = require('path')
const axios require('axios')
const apiRoutes = express.Router()
apiRoutes.get('/getDiscList', function (req, res) {
    var url = 'https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg'
    axios.get(url, {
        headers: {
            referer: 'https://c.y.qq.com/',
            host: 'c.y.qq.com'
        },
        params: req.query
    }).then((response) => {
        res.json(response.data)
    }).catch((e) => {
        console.log(e)
    })
})

module.exports = function(app){
    app.use('/api', apiRoutes)
}

请求结果如下,request URL是本地,由webpack-dev-server代理转发给远端

总结

在webpackDevServer.config.js中,也就是devServer对象的before方里,在传入的express的实例app上添加一些路由即可。create-react-app搭建代理(二)搭建更灵活的代理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
问题中提到了使用命令"create-react-app"时出现了"Unknown command: 'create-react-app'"的错误。 根据引用中的提示,如果改了环境变量还不行,你可以尝试使用命令"npx create-react-app react-cli-app"。这个命令会自动下载并执行create-react-app工具,从而创建React应用程序。 另外,引用中提到了一个解决方案。你可以右击"我的电脑",选择"属性",然后点击"高级系统设置",再点击"环境变量"。在安装Node.js时,你可以指定一个node_global的地址。将这个地址添加到环境变量的path中,这样就可以解决"Unknown command"的问题。 综上所述,你可以尝试使用命令"npx create-react-app react-cli-app"来创建React应用程序,并确保在环境变量中添加了正确的node_global地址。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [create-react-app不是内部或外部命令,也不是可运行的程序?](https://blog.csdn.net/qq_44930379/article/details/117525875)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [create-react-redux-app:基于create-react-appReact样板](https://download.csdn.net/download/weixin_42131443/15070891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值