【问题标题】:NextJS dynamic routing in Amazon CloudFrontAmazon CloudFront 中的 NextJS 动态路由
【发布时间】:2022-01-02 20:19:07
【问题描述】:

我有一个使用 NextJS 作为包装器的应用程序,我使用了NextJS's dynamic routing feature。由于 dns.com/path/page 未呈现,我在将其部署到 CloudFront 时遇到问题,而 CloudFront 预计它是 dns.com/path/page.html。我通过应用这个lambda-edge-nice-url 解决方案来解决它。它现在可以正常工作。但是,还有一个问题:NextJS 的动态路由。 dsn.com/path/subpath/123 应该可以工作,因为 123 是一个动态参数。但是,这不起作用。 In 仅在我访问dns.com/path/subpath/[id] 时返回页面,这当然是不正确的,因为 [id] 不是我要加载的参数。

最奇怪的是:如果我尝试直接访问上面所说的 URL,它会失败。但是,在应用程序内部,我有重定向用户的按钮和链接,并且可以正常工作。

从应用程序内部导航(在其回调中带有router.push 的按钮):

尝试直接访问网址:

谁能帮我正确路由请求?

【问题讨论】:

    标签: amazon-web-services next.js amazon-cloudfront nextjs-dynamic-routing


    【解决方案1】:

    我使用 CloudFront Lambda@Edge 源请求函数来处理将我的动态路由和静态路由重写到适当的 HTML 文件,以便 CloudFront 可以为任何路径提供预期文件。

    我的 lambda 函数看起来像

    export const handler: CloudFrontRequestHandler = async (event) => {
        const eventRecord = event.Records[0];
        const request = eventRecord.cf.request;
        const uri = request.uri;
    
        // handle /posts/[id] dynamic route
        if (uri === '/posts' || uri.startsWith('/posts/')) {
            request.uri = "/posts/[id].html";
            return request;
        }
        
        // if URI includes ".", indicates file extension, return early and don't modify URI
        if (uri.includes('.')) {
            return request;
        }
    
        // if URI ends with "/" slash, then we need to remove the slash first before appending .html
        if (uri.endsWith('/')) {
            request.uri = request.uri.substring(0, request.uri.length - 1);
        }
    
        request.uri += '.html';
        return request;
    };
    

    【讨论】:

    • 嗨,@LongZheng。您的代码不适用于我的场景。然而,它确实让我走上了正确的道路。 +1。我将在另一个答案中发布实际上对我有用的代码。谢谢!!!
    【解决方案2】:

    在尝试了很多不同的代码后,我终于想出了一个 Lambda 边缘表达式,它可以同时解决两个问题:

    • 需要在网址末尾插入.html
    • NextJS 动态路由在刷新或直接访问 URL 时不起作用。

    下面的代码基本上首先处理动态路由。它使用正则表达式来理解当前 URL 并将请求重定向到正确的 [id].html 文件。之后,如果没有匹配的正则表达式,并且 URL 不包含 .html 扩展名,则添加扩展名并检索正确的文件。

    const config = {
        suffix: '.html',
        appendToDirs: 'index.html',
        removeTrailingSlash: false,
    };
    
    const regexSuffixless = /\/[^/.]+$/; // e.g. "/some/page" but not "/", "/some/" or "/some.jpg"
    const regexTrailingSlash = /.+\/$/; // e.g. "/some/" or "/some/page/" but not root "/"
    const dynamicRouteRegex = /\/subpath\/\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b/; // e.g /urs/some-uuid; // e.g. '/subpath/uuid'
    
    exports.handler = function handler(event, context, callback) {
        const { request } = event.Records[0].cf;
        const { uri } = request;
        const { suffix, appendToDirs, removeTrailingSlash } = config;
        
        //Checks for dynamic route and retrieves the proper [id].html file
        if (uri.match(dynamicRouteRegex)) {
            request.uri = "/subpath/[id].html";
            callback(null, request);
            return;
        }
        
        
        // Append ".html" to origin request
        if (suffix && uri.match(regexSuffixless)) {
            request.uri = uri + suffix;
            callback(null, request);
            return;
        }
        
        // Append "index.html" to origin request
        if (appendToDirs && uri.match(regexTrailingSlash)) {
            request.uri = uri + appendToDirs;
            callback(null, request);
            return;
        }
    
        // Redirect (301) non-root requests ending in "/" to URI without trailing slash
        if (removeTrailingSlash && uri.match(/.+\/$/)) {
            const response = {
                // body: '',
                // bodyEncoding: 'text',
                headers: {
                    'location': [{
                        key: 'Location',
                        value: uri.slice(0, -1)
                     }]
                },
                status: '301',
                statusDescription: 'Moved Permanently'
            };
            callback(null, response);
            return;
        }
    
        // If nothing matches, return request unchanged
        callback(null, request);
    };
    

    非常感谢@LongZheng 的回答。出于某种原因,他的代码对我不起作用,但可能对某些人有用,所以请查看他的答案。另外,向 lambda-edge-nice-urls repo 的创建者 Manc 致敬。我的代码基本上是两者的混合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-16
      • 2020-09-08
      • 2021-08-12
      • 2020-08-25
      • 1970-01-01
      • 1970-01-01
      • 2020-10-16
      • 1970-01-01
      相关资源
      最近更新 更多