next.js+express+lru-cache自定义webServer

const express = require('express');
const next = require('next');
const path = require('path');
const fs = require('fs');
/*const favicon = require('serve-favicon');*/
const serveStatic = require('serve-static');
const compression = require('compression');
const helmet = require('helmet');
const LRUCache = require('lru-cache');
/*const redis = require('redis');*/
 const proxy = require('express-http-proxy');

const port = parseInt(process.env.PORT, 10) || 8003;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev ,dir:'./ssr'});
const handle = app.getRequestHandler();

// This is where we cache our rendered HTML pages
const ssrCache = new LRUCache({
    max: 100,
    maxAge: 1000 * 60 * 60 // 1hour
});
app.prepare()
    .then(() => {
        const server = express();
        /* helmet*/
        server.use(helmet());
        server.use(helmet.dnsPrefetchControl({ allow: true }));
        /* compress*/
        server.use(compression());
        /* static*/
        server.use(serveStatic(path.join(process.cwd(),'./www')));
        /* proxy*/
        server.use('/gateweb', proxy('http://172.28.65.33/',{
            proxyReqPathResolver (req) {
                return `/gateweb${req.url}`;
            }
        }));
        /* router*/
        server.get('/', (req, res) => {
            res.redirect('/portal/index');
        });
        server.get('/portal', (req, res) => {
            res.redirect('/portal/index');
        });
        // Use the `renderAndCache` utility defined below to serve pages
        server.get('/portal/index', (req, res) => {
            renderAndCache(req, res, '/index');
        });
        server.get('/portal/doc/md/:id', (req, res) => {
            /* const queryParams = { id: req.params.id };*/
            const {id} = req.params;
            renderAndCache(req, res, '/md', {id});
        });
        server.get('/portal/doc/sdk/:id', (req, res) => {
            /* const queryParams = { id: req.params.id };*/
            const {id} = req.params;
            renderAndCache(req, res, '/sdk', {id});
        });
        server.get('/portal/*', (req, res) => {
            res.setHeader('Content-Type','text/html; charset=utf-8');
            res.send(fs.readFileSync('./www/portalStatic/index.html'));
        });
        server.get('*', (req, res) => {
            return handle(req, res);
        });
        /* redis消息同步*/
        /*const sub = redis.createClient(8003, '172.28.65.33');
        const pub = redis.createClient(8003, '172.28.65.34');
        sub.on('subscribe', (channel, count) => {
            console.log(`${channel}:${count}`);               //  test channel:1
            pub.publish('test channel', 'channel message test');
        });
        sub.on('message', (channel, message) => {
            console.log(`${channel}-message:${JSON.stringify(message)}`);    // test channel-message:"channel message test"
        });
        sub.subscribe('test channel');*/
        server.listen(port, (err) => {
            if (err) { throw err; }
            console.log(`> Ready on http://localhost:${port}`);
        });
    });

/*
 * NB: make sure to modify this to take into account anything that should trigger
 * an immediate page change (e.g a locale stored in req.session)
 */
function getCacheKey (req) {
    return `${req.url}`;
}
async function renderAndCache (req, res, pagePath, queryParams) {
    const key = getCacheKey(req);

    // If we have a page in the cache, let's serve it
    if (ssrCache.has(key)) {
        res.setHeader('x-cache', 'HIT');
        res.send(ssrCache.get(key));
        return;
    }

    try {
        // If not let's render the page into HTML
        const html = await app.renderToHTML(req, res, pagePath, queryParams);

        // Something is wrong with the request, let's skip the cache
        if (res.statusCode !== 200) {
            res.send(html);
            return;
        }

        // Let's cache this page
        ssrCache.set(key, html);

        res.setHeader('x-cache', 'MISS');
        res.send(html);
    } catch (err) {
        app.renderError(err, req, res, pagePath, queryParams);
    }
}

proxy.js

module.exports = {
    '/gateweb': {
        target: 'http://172.28.65.33/',
        pathRewrite: { '^/gateweb': 'gateweb/' },
        changeOrigin: true,
        headers: {
            host: 'http://172.28.65.33/',
            origin: 'http://172.28.65.33/'
        }
    }
};

koa框架

const Koa = require('koa');
const next = require('next');
const Router = require('koa-router');
const path = require('path');
const favicon = require('koa-favicon');
const koaStatic = require('koa-static');
const compress = require('koa-compress');
const helmet = require('koa-helmet');
const fs = require('fs');
const proxy = require('koa-server-http-proxy');
const proxyConfig = require('./proxy');
const LRUCache = require('lru-cache');
const ssrCache = new LRUCache({
    max: 100,
    maxAge: 1000 * 60 * 60 // 1hour
});
const port = parseInt(process.env.PORT, 10) || 8003;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev ,dir:'./ssr'});
const handle = app.getRequestHandler();
app.prepare()
    .then(() => {
        const server = new Koa();
        const router = new Router();
        // favicon
        server.use(favicon(path.join(process.cwd(),'./www/portalStatic/favicon.ico')));
        // static
        server.use(koaStatic(path.join(process.cwd(),'./www')));
        // compress
        server.use(compress({
            filter (content_type) {
                return /text/i.test(content_type);
            },
            /* threshold: 1024,  //  Default 1024 bytes*/
            flush: require('zlib').Z_SYNC_FLUSH
        }));
        // helmet
        server.use(helmet());
        server.use(helmet.dnsPrefetchControl({ allow: true }));
        // bodyparser
        /* app.use(bodyParser());*/
        // proxy
        Object.keys(proxyConfig).forEach((context) => {
            const options = proxyConfig[context];
            server.use(proxy(context, options));
        });
        router.get('/portal/index', async ctx => {
            await app.render(ctx.req, ctx.res, '/index', ctx.query);
            ctx.respond = false;
        });
        router.get('/portal/doc/md/:id', async ctx => {
            const {id} = ctx.params;
            await app.render(ctx.req, ctx.res, '/md', {id});
            ctx.respond = false;
        });
        router.get('/portal/doc/sdk/:id', async ctx => {
            const {id} = ctx.params;
            await app.render(ctx.req, ctx.res, '/sdk', {id});
            ctx.respond = false;
        });
        router.get('/', async (ctx) => {
            ctx.redirect('/portal/index');
        });
        router.get('/portal', async (ctx) => {
            ctx.redirect('/portal/index');
        });
        router.get('/portal/*', async (ctx) => {
            ctx.compress = true;
            ctx.response.type = 'text/html';
            ctx.response.body = fs.createReadStream('./www/portalStatic/index.html');
        });
        router.get('*', async ctx => {
            await handle(ctx.req, ctx.res);
            ctx.respond = false;
        });
        /* server.use(async (ctx, next) => {
            try {
                await next();
                if (!ctx.body) {
                    ctx.status = 404;
                    ctx.redirect('/portal/404');
                }
            } catch (err) {
                ctx.response.status = err.statusCode || err.status || 500;
                ctx.response.body = {
                    message: err.message
                };
            }
        });*/

        server.use(async (ctx, next) => {
            ctx.res.statusCode = 200;
            await next();
        });
        server.use(router.routes()).use(router.allowedMethods());
        server.listen(port, () => {
            console.log(`> Ready on http://localhost:${port}`);
        });
    });

你可能感兴趣的:(next.js,express,lrucache)