无论路由如何,如何提供相同的静态文件?

时间:2018-09-23 01:13:44

标签: node.js reactjs webpack koa koa-router

我有一个React App。使用webpack,我可以进行生产。现在,我尝试设置一个小型koa服务器来提供由webpack生成的用于生产的静态文件。

所以我做到了

import Koa from 'koa'
import serve from 'koa-static'

const app = new Koa()

app.use(serve('dist/'))

app.listen(3001)

dist/是文件(index.html,bundle等)的目录。 这很好用,但仅适用于路由'/'(localhost:3001 /) 在我的应用程序中,我使用React Router,因此我需要通过示例登录/ login(localhost:3001 / login)。但是当我尝试时,我得到“未找到”。使用devServer(通过webpack),此路由可以很好地工作。无论路线如何,我都只需要始终服务/ dist。怎么做白衣考阿?

4 个答案:

答案 0 :(得分:1)

一种选择是拦截Koa中的react-router客户路由并将其重写为'/'以加载index.html和客户端资产。

const REACT_ROUTER_PATHS = [
  '/login',
  '/logout',
  '/other-client-path'
];

app
  .use(async (ctx, next) => {
    if (REACT_ROUTER_PATHS.includes(ctx.request.path)) {
      ctx.request.path = '/';
    }
    await next();
  })
  .use(serve('dist/'));

答案 1 :(得分:0)

如果koa像express-static,则返回“未找到”是正常的,因为存在的唯一文件是“ index.html”。 我的解决方案

import fs from 'fs';


app.use(serve('dist/'));
// If the file is not found by koa
// intercept all request and return index.html
// this way you can manage the request in React 
app.use((ctx, next) => {
    ctx.type = 'html';
    ctx.body = fs.readFileSync('./dist/index.html');
});

答案 2 :(得分:0)

好吧,我终于赢了

import Koa from 'koa'
import serve from 'koa-static'
import fs from 'fs'
import path from 'path'

const app = new Koa()
const dist = path.join(__dirname, 'dist')
let validRoutes

fs.readdir(dist, (err, files) => {
  if (err) return console.log('Unable to scan directory: ' + err)
  validRoutes = files
})

function isRouteValid (url) {
  if (!validRoutes || !url) return false
  return validRoutes.find(route => url.slice(1) === route)
}

app.use(async (ctx, next) => {
  if (!isRouteValid(ctx.url)) ctx.path = 'index.html'
  await next()
})

app.use(serve(dist))

app.listen(3010)

答案 3 :(得分:0)

根据生成的生成方式,仅查看生成的dist目录中的文件可能还不够。例如,如果您使用的是CRA,您可能还需要其他类似的东西,例如他们使用in this post在子目录中查找所有有效路由。所以您可能会有类似的东西

import Koa from 'koa';
import serve from 'koa-static';
import fs from 'fs';
import path from 'path';

const app = new Koa();
const dist = path.join(__dirname, 'dist');
let validRoutes;

var walk = function(dir, done) {
    var results = [];
    fs.readdir(dir, function(err, list) {
        if (err) return done(err);
        var i = 0;
        (function next() {
            var file = list[i++];
            if (!file) return done(null, results);
            file = path.resolve(dir, file);
            fs.stat(file, function(err, stat) {
                if (stat && stat.isDirectory()) {
                    walk(file, function(err, res) {
                        results = results.concat(res);
                        next();
                    });
                } else {
                    results.push(file);
                    next();
                }
           });
        })();
    });
};

walk(dist, function(err, results) {
    if (err) throw err;
    validRoutes = results;
});

function isRouteValid (r: string) {
    if (!validRoutes || !r) return false;
    return validRoutes.find(route => r === route);
}

app.use(async (ctx, next) => {
    if (!isRouteValid(path.resolve(dist, ctx.url.slice(1)))) ctx.path = 'index.html';
    await next();
});

app.use(serve(dist));

app.listen(3010);