NuxtJS V2 优化
以下这些都是在项目中实践过的优化方法,不过现在 Nuxt 升级到 V3 了,这些方法都不适用了。
移除未使用的CSS
1render: {2 route: (url, result) => {3 // Tailwindcss 内联到 html 中是未压缩的,原因未知4 // 所以在 render 时使用 cleanCSS 压缩5 const { html } = result;6 const STYLE_PATTERN = /<style[^>]*>([\\s\\S]*?)<\\/[^>]*style>/gi;7 const replaceHTML = html.replace(STYLE_PATTERN, ($0, $1) => {8 const context = [];9 context.push('<style>');10 const { styles } = new CleanCSS().minify($1);11 context.push(styles);12 context.push('</style>');13 return context.join('');14 });15 result.html = replaceHTML;16 },17 }
动态增加Script
1hooks: {2 route: (url, result, { req }) => {3 // 支付宝小程序,需要加入特定的 js4 // 目前轻交互会在小程序打开5 const { headers } = req;6 const { html } = result;7 const userAgent = headers['user-agent'] || '';8 const isAliAPP = userAgent.toLocaleLowerCase().includes('aliapp');9 if (!isAliAPP) {10 return;11 }12 const aliAPPScript =13 '<script src="<https://appx/web-view.min.js>"></script></head>';14 result.html = html.replace(/<\\/head>/i, aliAPPScript);15 },16 }
减少__Nuxt__体积
NuxtJS 在使用服务端渲染时,会自动往HTML注入当前页面使用的数据,对于只有渲染的页面,在客户端根本用不到这些数据,如果是列表页面,这些数据会偏大,导致整个页面体积变大,造成传输耗时。
诉求是:把用不到的这些数据在页面渲染时去掉。
方案是:利用 NuxtJS 提供的渲染 Hook 解决,代码如下:
1hooks: {2 'vue-renderer': {3 'ssr:templateParams': (templateParams, renderContext) => {4 const { APP } = templateParams;5 const { nuxt } = renderContext;6 const { ...state } = nuxt;7 const { config } = state;8 // 去掉 window.__NUXT__ 没有用的信息,只保留环境信息,减少页面体积9 // 环境信息是必须的,不能去掉10 const PATTERN = /<script>window\\.__NUXT__=([\\s\\S]*?)<\\/[^>]*script>/i;11 const replaceHTML = APP.replace(PATTERN, () => {12 const stateScript = `window.__NUXT__=${devalue({13 config,14 })};`;15 return `<script>${stateScript}</script>`;16 });17 Object.assign(templateParams, {18 APP: replaceHTML,19 });20 },21 },22},
增加页面级缓存
在 middleware 新建 page-cache.js ,代码如下:
1const LRU = require('lru-cache');2export const CACHE = new LRU({3 // 缓存队列长度 最大缓存数量4 max: 100,5 // 缓存时间 单位:毫秒6 maxAge: 1000 * 60 * 60 * 24,7});8export default (req, res, next) => {9 if (process.env.NODE_ENV !== 'production') {10 next();11 return;12 }13 const cacheKey = 'NPS_PAGE';14 const cacheObj = CACHE.get(cacheKey);15 if (cacheObj) {16 res.setHeader('Content-Type', ' text/html; charset=utf-8');17 res.end(cacheObj.html, 'utf-8');18 return;19 }20 res.original_end = res.end;21 res.end = (data) => {22 if (res.statusCode === 200) {23 CACHE.set(cacheKey, {24 html: data,25 });26 }27 res.original_end(data, 'utf-8');28 };29 next();30};
在 nuxt.config.js 中启用:
serverMiddleware: ['~/middleware/page-cache.js'],
增加模版变量
uxtJS 在渲染页面时,只有固定几个变量,比如:APP、ENV、HEAD 等。而这些远远满足不了自定义的需求。
举个现实的场景:项目中,有些页面使用灵犀系统上报埋点,有些页面不使用,如果把灵犀代码放到统一的页面入口中,对于不使用灵犀的页面而言,反而增加了一个多余的网络请求,影响页面性能。
我们的诉求是,能根据页面路径,动态的追加灵犀代码。
这就需要借助 NuxtJS 提供的 Hooks 来支持。在 nuxt.config.js 增加 hooks ,代码如下:
1hooks: {2 'vue-renderer': {3 'ssr:templateParams': (templateParams, renderContext) => {4 const { nuxt } = renderContext;5 const { routePath } = nuxt || {};6 const whiteList = [7 '/light-portal.html',8 '/light-portal/material-detail.html',9 '/light-portal/material.html',10 ];11 // 只有特定页面才加入灵犀12 const shouldAppendLX = whiteList.includes(routePath);13 // 追加 IS_APPEND_LX 全局变量,便于在页面中使用14 Object.assign(templateParams, {15 IS_APPEND_LX: shouldAppendLX,16 });17 },18 },19}
在 app.html 使用 「IS_APPEND_LX」变量动态输出 灵犀脚本:
1{% if (IS_APPEND_LX) { %}2 <script src="//lx.meituan.net/lx.5.min.js"></script>3 <script>4 !function(n,t,e){if(n["_MeiTuanALogObject"]=e,!n[e]){var u=function(){let n=function(){let t=function(){t.q.push([arguments,+new Date])};return t.q=[],n.q.push([arguments,t]),t};return n.q=[],n.t=+new Date,u.q.push([arguments,n]),n};u.q=u.q||[],u.l=+new Date,n[e]=u}}(window,document,"LXAnalytics");5 LXAnalytics('config', {6 defaultCategory:'cs_smart_portal',7 defaultCid: 'c_cs_smart_portal_ntwfxrrs',8 isSPA: false,9 isDev: {{ process.env.ENV !== 'prod' }},10 onWebviewAppearAutoPV: false,11 onVisibilityChangeAutoPV: false,12 onWindowFocusAutoPV: false,13 onVCGap: 2,14 nativeReport:'off',15 use_post: true,16 });17 </script>18{% } %}