无论路由如何,如何提供相同的静态文件?
How to serve the same static files regardless of the route?
我有一个 React 应用程序。我使用 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、捆绑包等)所在的目录。
这很有效,但仅适用于路由 '/' (localhost:3001/)
在我的应用程序中,我使用了 React 路由器,因此我需要通过示例转到 /login (localhost:3001/login)。但是当我尝试时,我得到 "Not Found"。对于 devServer(通过 webpack),这条路线运行良好。我只需要始终服务 /dist,无论路线如何。如何使用 koa 做这个?
一种选择是拦截 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/'));
如果 koa 像 express-static
,他 returns 'Not Found' 是正常的,因为唯一存在的文件是 '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');
});
好吧我终于赢了
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)
根据构建的生成方式,仅查看生成的 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);
我有一个 React 应用程序。我使用 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、捆绑包等)所在的目录。
这很有效,但仅适用于路由 '/' (localhost:3001/)
在我的应用程序中,我使用了 React 路由器,因此我需要通过示例转到 /login (localhost:3001/login)。但是当我尝试时,我得到 "Not Found"。对于 devServer(通过 webpack),这条路线运行良好。我只需要始终服务 /dist,无论路线如何。如何使用 koa 做这个?
一种选择是拦截 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/'));
如果 koa 像 express-static
,他 returns 'Not Found' 是正常的,因为唯一存在的文件是 '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');
});
好吧我终于赢了
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)
根据构建的生成方式,仅查看生成的 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);