我有一个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。怎么做白衣考阿?
答案 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);