كيفية تكوين تثبيت متغيرات بيئة Nuxt.js في وقت التشغيل ، أو كيفية القيام بكل شيء لا يحب الجميع ولا نأسف لذلك


( توضيح )

يواصل كبار مطوري الويب أنطون وأليكسي قصة الصراع الصعب مع Nuxt. في الجولة السابقة من المعركة مع هذا الإطار ، أظهروا كيفية إطلاق مشروع على Nuxt بحيث يكون الجميع سعداء. في مقال جديد سنتحدث عن التطبيق الحقيقي للإطار.

بدأنا بإعادة كتابة المشروع بدين تقني ضخم. كان الجمهور الشهري 6-7 مليون زائر فريد ، لكن النظام الأساسي الحالي تسبب في العديد من المشاكل. لذلك ، تقرر إرسالها إلى التقاعد. بالطبع ، كان الأداء هو مصدر قلقنا الأكبر ، لكنني لم أرغب أيضًا في إضاعة تحسين محركات البحث.

بعد جولتين من المناقشة ، قرروا عدم الاعتماد على النهج التقليدي من خلال العرض من جانب الخادم فقط - ولكن ليس في وضع أنفسهم في العرض من جانب العميل. ونتيجة لذلك ، بدأنا في بناء حل يستند إلى Nuxt.js.

Nuxt.js حسن البالغ من العمر


نحن نأخذ "إطار عمل إطار العمل" استنادًا إلى Vue.js ، المعروف لنا بالفعل في المقالة الأخيرة ، لبناء تطبيقات عالمية لخادم العميل. في حالتنا ، يعمل التطبيق جنبًا إلى جنب مع واجهة برمجة التطبيقات المعقدة إلى حد ما (تعقيدات الخدمات الصغيرة ، ولكن في ذلك الوقت الآخر) والعديد من طبقات التخزين المؤقت ، فإنه يعرض المحتوى الذي يمكن تحريره بواسطة المحررين ويعيد المحتوى الثابت بالفعل للحصول على أداء سريع. عظيم ، صحيح؟

في الواقع ، لا يوجد شيء جديد هنا. ولكن ما يجعل Nuxt.js مثيرًا للاهتمام هو القدرة على بدء مشروع بسرعة مع عرض خادم العميل. في بعض الأحيان تحتاج إلى أن تتعارض مع الإطار المحدد للإطار. هذا ما فعلناه.

لا وقت للشرح والبناء مرة واحدة ونشر الكثير!


في يوم من الأيام اقتربت منا شركة تيكلايد وحيرة: كلما دفعنا التغييرات في المستودع ، نحتاج إلى بناء كل من البيئات (بيئات التطوير والمرحلة والمنتج) بشكل منفصل. كانت بطيئة. ولكن ما الفرق بين هذه البنى؟ نعم ، فقط في متغيرات البيئة! وما طلب القيام به يبدو منطقيا ومعقولا. لكن رد فعلنا الأول كان: O_o

بناء مرة واحدة ، نشر العديد من الاستراتيجية أمر منطقي في عالم تطوير البرمجيات. ولكن في عالم جافا سكريبت ... لدينا مجموعة كاملة من المترجمات ، والناقلات ، والمعالجات السابقة واللاحقة ، وكذلك الاختبارات والنسالة. كل هذا يستغرق بعض الوقت لتكوينها لكل من البيئات. بالإضافة إلى ذلك ، هناك العديد من المشاكل المحتملة لتسرب البيانات السرية (الأسرار ، مفاتيح API ، وما إلى ذلك التي يمكن تخزينها في التكوينات).

وبدأنا


بالطبع ، بدأنا ببحث على جوجل. ثم تحدثنا مع مشرف Nuxt.js ، ولكن دون نجاح كبير. ماذا أفعل - كان علي أن أتوصل إلى حل بمفردي ، ولا أنسخه من StackOverflow (هذا هو أساس نشاطنا ، أليس كذلك؟).

دعونا نكتشف كيف يقوم Nuxt.js بذلك.


يحتوي Nuxt.js على ملف تكوين بالاسم المتوقع nuxt.config.js. يتم استخدامه لنقل التكوينات إلى التطبيق برمجياً:

const config = require('nuxt.config.js') const nuxt = new Nuxt(config) 

من الممكن ضبط البيئة من خلال متغيرات بيئية. بشكل عام ، من الممارسات الشائعة إلى حد ما توصيل ملف التكوين ديناميكيًا. ثم يتم نقل كل هذا إلى حزمة ويب ويبجبل بلوجين ويمكن استخدامه على العميل والخادم ، مثل هذا:

process.env.propertyName
// أو
context.env.propertyName.

يتم خبز هذه المتغيرات أثناء التجميع ، لمزيد من المعلومات هنا: صفحة Nuxt.js env .
هل لاحظت حزمة الويب؟ نعم ، هذا يعني التجميع ، وهذا ليس ما نريده.

لنجرب بشكل مختلف


فهم كيفية عمل Nuxt.js يعني بالنسبة لنا:

  • لم يعد بإمكاننا استخدام env داخل nuxt.config.js ؛
  • يجب تمرير أي متغيرات ديناميكية أخرى (على سبيل المثال ، داخل head.meta) إلى كائن nuxt.config.js في وقت التشغيل.


الكود في الخادم / index.js:

 const config = require('../nuxt.config.js') 

التغيير إلى:

 //    Nuxt.js const config = require('./utils/extendedNuxtConfig.js').default 

حيث الأدوات / extNuxtConfig.js:

 import config from 'config' import get from 'lodash/get' //   Nuxt.js const defaultConfig = require('../../nuxt.config.js') //   const extendedConfig = {} //   Nuxt.js const nuxtConfig = { ...defaultConfig, ...extendedConfig } //     //       if (get(nuxtConfig, 'head.meta')) { nuxtConfig.head.meta.push({ hid: 'og:url', property: 'og:url', content: config.get('app.canonical_domain') }) } export default nuxtConfig 

لم نلاحظ الفيل حتى


حسنًا ، لقد حللنا مشكلة الحصول على متغيرات ديناميكية من خارج خاصية env لكائن التكوين في nuxt.config.js. لكن المشكلة الأصلية لم تحل بعد.

كان هناك افتراض بأنه سيتم استخدام بعض abstractEnv.js المجرد في:

  • العميل - قم بإنشاء ملف env.js ليتم تنزيله عالميًا (window.env.envKey) ،
  • الخادم - يتم استيراده إلى الوحدات ، عند الضرورة ،
  • شفرة متشابهة ، شيء من هذا القبيل
    السياق. العميل؟ window.env [مفتاح]: global.sharedEnv [مفتاح].

بطريقة ما ليست كبيرة. سيحل هذا التجريد المشكلة الأكثر خطورة - تسرب البيانات السرية إلى تطبيق العميل ، حيث سيكون من الضروري إضافة القيمة بوعي.

سوف يساعدنا Vuex


أثناء التحقيق في المشكلة ، لاحظنا أن متجر Vuex يتم تصديره إلى كائن نافذة. يضطر هذا الحل لدعم تشابه Nuxt ، شبيبة. Vuex هو مستودع بيانات مستوحى من Flux مصمم خصيصًا لتطبيقات Vue.js.

حسنًا ، لماذا لا تستخدمه لمتغيراتنا المشتركة؟ هذا هو نهج أكثر عضوية - البيانات في مستودع عالمي يناسبنا.

لنبدأ بالخادم / utils / SharedEnv.js:

 import config from 'config' /** *  ,      *  ,     *  ,       * * @type {Object} */ const sharedEnv = { // ... canonicalDomain: config.get('app.canonical_domain'), } export default sharedEnv 

سيتم تنفيذ الرمز أعلاه أثناء بدء تشغيل الخادم. ثم أضفه إلى مستودع Vuex:

 /** *   . *        * .   * https://nuxtjs.org/guide/vuex-store/#the-nuxtserverinit-action * * @return {Object} Shared environment variables. */ const getSharedEnv = () => process.server ? require('~/server/utils/sharedEnv').default || {} : {} // ... export const state = () => ({ // ... sharedEnv: {} }) export const mutations = { // ... setSharedEnv (state, content) { state.sharedEnv = content } } export const actions = { nuxtServerInit ({ commit }) { if (process.server) { commit('setSharedEnv', getSharedEnv()) } } } 

سوف نعتمد على حقيقة أن nuxtServerInit يتم إطلاقه أثناء تهيئة الخادم. توجد بعض الصعوبات: انتبه إلى طريقة getSharedEnv ، وهنا يضاف التحقق من التنفيذ المتكرر على الخادم.

ماذا حدث


الآن لدينا متغيرات شائعة يمكن استخلاصها في مكونات مثل هذه:
هذا. $ store.state.sharedEnv.canonicalDomain

النصر!

أوه لا. ماذا عن الإضافات؟


تتطلب بعض المكونات الإضافية متغيرات البيئة لتكوينها. وعندما نريد استخدامها:
Vue.use (MyPlugin، {someEnvOption: 'لا يوجد وصول إلى متجر vuex'})

رائع ، حالة العرق ، يحاول Vue.js تهيئة نفسه قبل تسجيل Nuxt.js SharedEnvobject في مستودع Vuex.

على الرغم من أن الوظيفة التي تسجل الإضافات توفر الوصول إلى كائن السياق الذي يحتوي على رابط المستودع ، لا يزال SharedEnv فارغًا. يتم حل هذا ببساطة شديدة - دعنا نجعل المكون الإضافي وظيفة غير متزامنة وننتظر تنفيذ nuxtServerInit:

 import Vue from 'vue' import MyPlugin from 'my-plugin' /** *   MyPlugin . */ export default async (context) => { //  ,      sharedEnv await context.store.dispatch('nuxtServerInit', context) const env = { ...context.store.state.sharedEnv } Vue.use(MyPlugin, { option: env.someKey }) } 

الآن هو النصر.

Source: https://habr.com/ru/post/ar429756/


All Articles