3

我有一个反应应用程序。使用 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/) 在我的应用程序中,我使用反应路由器,所以我需要通过示例转到 /login (localhost:3001/login)。但是当我尝试时,我得到“未找到”。使用 devServer(通过 webpack),这条路线运行良好。我只需要始终为 /dist 服务,无论路线如何。如何做到这一点?

4

4 回答 4

4

一种选择是拦截 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/'));
于 2018-09-23T02:00:35.583 回答
3

如果 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');
});
于 2018-09-23T08:57:57.093 回答
2

好吧,我终于赢了

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)
于 2018-09-23T13:38:25.197 回答
0

根据生成的构建方式,仅查看生成dist目录中的文件可能还不够。例如,如果您使用 CRA,您可能需要更类似于他们在这篇文章中使用的东西来查找子目录中的所有有效路线。所以你可能有一些看起来像

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);
于 2020-10-30T16:18:44.057 回答