يضيف next-boost طبقة ذاكرة التخزين المؤقت إلى تطبيقات SSR (عرض من جانب الخادم). تم بناؤه في الأصل لـ Next.js ويجب أن تعمل مع أي تطبيق Node.js http.Server .
يحقق next-boost أداءً رائعًا من خلال تقديم صفحات ويب على worker_threads أثناء تقديم المخزونات المخزنة مؤقتًا على الخيط الرئيسي.
إذا كنت على دراية بـ Next.js ، يمكن اعتبار next-boost بمثابة تنفيذ لتجديد ثابت ثابت يعمل مع getServerSideProps . وليس المقصود استخدامه مع getStaticProps ، حيث ستقوم Next.js بعمل ذاكرة التخزين المؤقت لك.
$ yarn add @next-boost/next-boost
$ yarn add @next-boost/redis-cache # using load-balancer and cluster
$ yarn add @next-boost/hybrid-disk-cache # simple site with disk cache next startworker_threads لـ SSR.next-boost.redis.js للعينة.next-boost.hdc.js لعينة التكوين next-boost CLI مع Next.js بعد تثبيت الحزمة ، ما عليك سوى تغيير البرنامج النصي START من next start إلى next-boost . جميع وسيطات سطر أوامر next start ، مثل -p لتحديد المنفذ ، متوافقة.
"scripts": {
...
"start": "next-boost", // previously `next start`
...
},
هناك مثال تحت examples/nodejs ، والذي يعمل مع http.Server عادي.
لاستخدامه مع express.js و next.js ، يرجى التحقق من examples/with-express .
باستخدام worker_threads ، لن يؤدي عرض SSR الثقيل في وحدة المعالجة المركزية إلى منع العملية الرئيسية من تقديم ذاكرة التخزين المؤقت.
فيما يلي مقارنة استخدام ApacheBench على منشور مدونة تم جلبه من قاعدة البيانات. HTML Prerendered وعملية DB تستغرق حوالي 10 ~ 20ms. تستغرق الصفحة حوالي 200 مللي ثانية لـ Next.js لتقديمها.
$ /usr/local/bin/ab -n 200 -c 8 http://127.0.0.1:3000/blog/posts/2020/3/postnameليس معيارًا علميًا ، لكن التحسينات ضخمة بشكل واضح.
مع next start (البيانات التي تم جلبها باستخدام getServerSideProps ):
Document Length: 76424 bytes
Concurrency Level: 8
Time taken for tests: 41.855 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 15325600 bytes
HTML transferred: 15284800 bytes
Requests per second: 4.78 [#/sec] (mean)
Time per request: 1674.185 [ms] (mean)
Time per request: 209.273 [ms] (mean, across all concurrent requests)
Transfer rate: 357.58 [Kbytes/sec] received
مع CLI next-boost :
Document Length: 78557 bytes
Concurrency Level: 8
Time taken for tests: 0.149 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 15747600 bytes
HTML transferred: 15711400 bytes
Requests per second: 1340.48 [#/sec] (mean)
Time per request: 5.968 [ms] (mean)
Time per request: 0.746 [ms] (mean, across all concurrent requests)
Transfer rate: 103073.16 [Kbytes/sec] received
حتى أنه يتفوق على صفحة static static التي تم إنشاؤها ( getStaticProps ) ، مع التعامل مع 2 ~ 2.5x في ثوانٍ في بيئتي.
ينفذ next-boost ذاكرة التخزين المؤقت من جانب الخادم بطريقة لا معنى لها. عند الوصول إلى صفحة منتهية الصلاحية ( stale ) ، سيتم تقديم ذاكرة التخزين المؤقت وفي الوقت نفسه ، ستجلب عملية الخلفية أحدث إصدار ( revalidate ) من تلك الصفحة وحفظه على ذاكرة التخزين المؤقت.
سيقوم التكوين التالي بتخزين Cache Uris مطابقة ^/blog.* . سيتم التعامل مع rules مطابقة الصفحات فقط من قبل next-boost وليس هناك قواعد exclude .
module . exports = {
rules : [ { regex : '^/blog.*' , ttl : 300 } ] ,
}هناك معلمتان للتحكم في سلوك ذاكرة التخزين المؤقت:
ttl (time-to-live) : بعد ثواني ttl ، سيتم إعادة تقييم ذاكرة التخزين المؤقت. وسيتم تحديث ttl في الصفحة المخزنة مؤقتًا عند إعادة تقييم الصفحة.tbd (time-before-deletion) : عندما لا يتم ضرب الصفحة مرة أخرى في ثواني ttl + tbd ، سيتم إزالتها تمامًا من ذاكرة التخزين المؤقت. أعلاه: فقط تخزين صفحات التخزين المؤقت مع عنوان URL تبدأ مع /blog .
من خلال إرسال GET مع Boost x-next-boost:update إلى عنوان URL ، سيتم إعادة تقييم ذاكرة التخزين المؤقت. وإذا لم تعد الصفحة موجودة ، فسيتم حذف ذاكرة التخزين المؤقت.
$ curl -H x-next-boost:update https://the_server_name.com/path_aإذا كنت ترغب في حذف صفحات mifiple مرة واحدة ، يمكنك تشغيل SQL على ذاكرة التخزين المؤقت مباشرة:
sqlite3 /cache_path/cache.db " update cache set ttl=0 where key like '%/url/a%'; " سيؤدي ذلك إلى إجبار جميع عناوين URL التي تحتوي /url/a على إعادة تقييمها عند الوصول في المرة القادمة.
سيقوم حذف cache_path بإزالة جميع ذاكرة التخزين المؤقت.
بشكل افتراضي ، سيتم تخزين كل صفحة ذات عناوين URL مختلفة بشكل منفصل. ولكن في بعض الحالات ، تريد ، /path_a?utm_source=twitter يتم تقديمه مع نفس محتويات /path_a . paramFilter هو لتصفية معلمات الاستعلام.
// in .next-boost.js
{
...
paramFilter : ( p ) = > p !== 'utm_source'
}بشكل افتراضي ، سيتم استخدام عنوان URL كمفتاح للصفحات المخزنة مؤقتًا. إذا كنت ترغب في الحصول على صفحات خادم من مجالات مختلفة أو بواسطة وكيل مستخدم مختلف ، فيمكنك استخدام هذه الوظيفة لتخصيص مفتاح ذاكرة التخزين المؤقت.
ملحوظات:
string ، فسيتعطل الخادم الخاص بك. // in .next-boost.js
{
...
cacheKey : ( req ) = > ( req . headers . host || '' ) + ':' + req . url
}بدلاً من ذلك ، يمكنك توفير وظيفة بدلاً من صفيف داخل التكوين الخاص بك.
// in .next-boost.js
{
...
rules : ( req ) = > {
if ( req . url . startsWith ( '/blog' ) ) {
return 300
}
}
} يجب إرجاع الوظيفة ttl صالحة للطلب. إذا كانت الوظيفة تُرجع 0 أو قيمة falsy ، فلن يتم تخزين الطلب مؤقتًا.
القوة التي تأتي من هذه الطريقة هي أنه يمكنك تحديد ما إذا كان الطلب مخبأة أم لا أكثر ديناميكية.
على سبيل المثال ، يمكنك تجاهل جميع الطلبات من المستخدمين المصادقين تلقائيًا بناءً على الرأس:
// in .next-boost.js
{
...
rules : ( req ) = > {
if ( req . headers . authorization ) {
return false
}
return 10 // cache all other requests for 10 seconds
}
}يمكنك أيضًا الحصول على قواعد أكثر تعقيدًا بسهولة أكبر ثم من خلال Regex. على سبيل المثال ، تتمنى TTL مختلف لكل صفحات ترقيم الصفحات.
// in .next-boost.js
{
...
rules : ( req ) = > {
const [ , p1 ] = url . split ( '?' , 2 )
const params = new URLSearchParams ( p1 )
return {
1 : 5000 ,
2 : 4000 ,
3 : 3000 ,
4 : 2000
} [ params . get ( 'page' ) ] || 1000
}
}على الرغم من أنك ستحتاج إلى كتابة قاعدة regex معقدة أو من المحتمل أن تكون هناك قواعد سهلة القيام بذلك من خلال منطق JS.
في النهاية إذا كنت تفضل كتابة Regex ولكن ترغب في الاستفادة من منطق JS ، يمكنك دائمًا إعادة مطابقة المباراة داخل معالج القواعد.
إذا كان ذلك متاحًا ، سيتم استخدام .next-boost.js في جذر المشروع. إذا كنت تستخدم التزويد التالي برمجيًا ، فيمكن تغيير اسم الملف في الخيارات التي انتقلت إليها إلى CachedHandler .
نصائح: إذا كنت تستخدم next-boost CLI مع NEXT.JS ، فقد ترغب في استخدام ملف التكوين.
وهنا مثال .next-boost.sample.js في الريبو.
interface HandlerConfig {
filename ?: string
quiet ?: boolean
cache ?: {
ttl ?: number
tbd ?: number
path ?: string
}
rules ?: Array < URLCacheRule > | URLCacheRuleResolver
paramFilter ?: ParamFilter
cacheKey ?: CacheKeyBuilder
}
interface URLCacheRule {
regex : string
ttl : number
}
type URLCacheRuleResolver = ( req : IncomingMessage ) => number
type ParamFilter = ( param : string ) => boolean
type CacheKeyBuilder = ( req : IncomingMessage ) => string يتم تمكين التسجيل بشكل افتراضي. إذا كنت تستخدم next-boost برمجيًا ، فيمكنك تعطيل السجلات عن طريق تمرير العلم المنطقي quiet كخيار لـ CachedHandler .
...
const cached = await CachedHandler ( args , { quiet : true } ) ;
... هناك أيضًا علامة --quiet إذا كنت تستخدم سطر الأوامر.
next-boost محدود. حتى يتم ضرب عنوان URL على كل خادم خلفي ، لا يزال بإمكانه تفويت ذاكرة التخزين المؤقت. استخدم الوكيل العكسي مع دعم ذاكرة التخزين المؤقت (Nginx ، الورنيش وما إلى ذلك) لذلك.GET على طلبات HEAD فقط.worker_threads وهي ميزة Node.js 12+. يعمل next-boost كبديل للمكان next start باستخدام ميزة Server Custom Server Next.js.
في الصفحة المرتبطة أعلاه ، يمكنك رؤية الإشعار التالي:
قبل اتخاذ قرار استخدام خادم مخصص ، يرجى مراعاة أنه يجب استخدامه فقط عندما لا يمكن لجهاز التوجيه المدمج لـ NEXT.JS تلبية متطلبات التطبيق الخاصة بك. سيقوم الخادم المخصص بإزالة تحسينات الأداء المهمة ، مثل وظائف الخادم والتحسين الثابت التلقائي.
من المفترض أن يتم استخدام التعزيز التالي على Cloud VPS أو الحاويات ، لذلك فإن وظيفة الخادم ليست مشكلة هنا. بالنسبة Automatic Static Optimization ، لأننا لا نقوم بأي app.render Render هنا ، لا يزال يعمل ، كما هو الحال دائمًا.
إليك المقالة حول عدم استخدام SQLite. وبالنسبة لـ Next-Boost الرئيسية: SSR Faster SSR على VPS منخفضة التكلفة ، على حد علمي ، فهو الخيار الأفضل.
معهد ماساتشوستس للتكنولوجيا. حقوق الطبع والنشر 2020 راكوراكو جيو.