การสร้างแอป Vue.js ที่แสดงผลทางฝั่งเซิร์ฟเวอร์โดยใช้ Nuxt.js
เผยแพร่แล้ว: 2022-03-11เฟรมเวิร์ก/ไลบรารี JavaScript เช่น Vue สามารถมอบประสบการณ์ผู้ใช้ที่ยอดเยี่ยมเมื่อเรียกดูไซต์ของคุณ ส่วนใหญ่มีวิธีการเปลี่ยนแปลงเนื้อหาของหน้าแบบไดนามิกโดยไม่ต้องส่งคำขอไปยังเซิร์ฟเวอร์ในแต่ละครั้ง
อย่างไรก็ตาม แนวทางนี้มีปัญหา เมื่อเริ่มโหลดเว็บไซต์ของคุณในครั้งแรก เบราว์เซอร์ของคุณจะไม่ได้รับหน้าที่สมบูรณ์ที่จะแสดง แทนที่จะถูกส่งไปเพื่อสร้างเพจ (HTML, CSS, ไฟล์อื่น ๆ ) และคำแนะนำในการรวมเข้าด้วยกัน (เฟรมเวิร์ก/ไลบรารี JavaScript) ต้องใช้เวลาพอสมควรในการรวบรวมข้อมูลทั้งหมดนี้ ก่อนที่เบราว์เซอร์ของคุณจะมีบางอย่างที่จะแสดง มันเหมือนกับการส่งหนังสือหลายเล่มพร้อมกับตู้หนังสือแบบแบน คุณต้องสร้างตู้หนังสือก่อนแล้วจึงเติมหนังสือให้เต็ม
วิธีแก้ปัญหานี้ฉลาดมาก: มีเวอร์ชันของเฟรมเวิร์ก/ไลบรารีบน เซิร์ฟเวอร์ ที่สามารถสร้างเพจที่พร้อมแสดงได้ จากนั้นส่งหน้าที่สมบูรณ์นี้ไปยังเบราว์เซอร์พร้อมกับความสามารถในการเปลี่ยนแปลงเพิ่มเติมและยังคงมีเนื้อหาของหน้าแบบไดนามิก (เฟรมเวิร์ก/ไลบรารี) เหมือนกับการส่งตู้หนังสือสำเร็จรูปพร้อมกับหนังสือบางเล่ม แน่นอน คุณยังคงต้องใส่หนังสือในตู้หนังสือ แต่คุณมีของที่ใช้งานได้ทันที
นอกเหนือจากการเปรียบเทียบแบบโง่ๆ แล้ว ยังมีข้อดีอื่นๆ อีกมากมาย ตัวอย่างเช่น หน้าที่ไม่ค่อยมีการเปลี่ยนแปลง เช่น หน้าเกี่ยวกับเรา ไม่จำเป็นต้องสร้างใหม่ทุกครั้งที่ผู้ใช้ขอ ดังนั้นเซิร์ฟเวอร์สามารถสร้างได้เพียงครั้งเดียวแล้วแคชหรือเก็บไว้ที่ใดที่หนึ่งเพื่อใช้ในอนาคต การปรับปรุงความเร็วประเภทนี้อาจดูเล็กน้อย แต่ในสภาพแวดล้อมที่เวลาจนกว่าการตอบสนองจะวัดเป็นมิลลิวินาที (หรือน้อยกว่า) ทุก ๆ บิตจะมีความสำคัญ
หากคุณต้องการข้อมูลเพิ่มเติมเกี่ยวกับข้อดีของ SSR ในสภาพแวดล้อม Vue คุณควรตรวจสอบบทความของ Vue เกี่ยวกับ SSR มีตัวเลือกมากมายเพื่อให้ได้ผลลัพธ์เหล่านี้ แต่ตัวเลือกที่ได้รับความนิยมมากที่สุด ซึ่งแนะนำโดยทีม Vue เช่นกันคือ Nuxt
ทำไมต้อง Nuxt.js
Nuxt.js มีพื้นฐานมาจากการใช้งาน SSR สำหรับไลบรารี React ยอดนิยมที่เรียกว่า Next หลังจากเห็นข้อดีของการออกแบบนี้แล้ว การใช้งานที่คล้ายกันนี้ได้รับการออกแบบสำหรับ Vue ที่เรียกว่า Nuxt ผู้ที่คุ้นเคยกับชุดค่าผสม React+Next จะสังเกตเห็นความคล้ายคลึงกันมากมายในการออกแบบและเลย์เอาต์ของแอปพลิเคชัน อย่างไรก็ตาม Nuxt นำเสนอคุณลักษณะเฉพาะของ Vue เพื่อสร้างโซลูชัน SSR ที่ทรงพลังและยืดหยุ่นสำหรับ Vue
Nuxt ได้รับการอัปเดตเป็นเวอร์ชัน 1.0 ที่พร้อมใช้งานจริงในเดือนมกราคม 2018 และเป็นส่วนหนึ่งของชุมชนที่มีการใช้งานและได้รับการสนับสนุนอย่างดี สิ่งที่ยอดเยี่ยมอย่างหนึ่งคือการสร้างโปรเจ็กต์โดยใช้ Nuxt นั้นไม่ได้แตกต่างจากการสร้างโปรเจ็กต์ Vue อื่นๆ มากนัก อันที่จริง มันมีฟีเจอร์มากมายที่ช่วยให้คุณสร้างฐานโค้ดที่มีโครงสร้างอย่างดีในระยะเวลาที่ลดลง
สิ่งสำคัญอีกอย่างที่ควรทราบคือ Nuxt ไม่จำเป็นต้องใช้สำหรับ SSR ได้รับการส่งเสริมเป็นเฟรมเวิร์กสำหรับการสร้างแอปพลิเคชัน Vue.js สากลและรวมถึงคำสั่ง ( nuxt generate
) สำหรับการสร้างแอปพลิเคชัน Vue ที่สร้างขึ้นแบบคงที่โดยใช้ codebase เดียวกัน ดังนั้นหากคุณวิตกเกี่ยวกับการดำดิ่งสู่ SSR ก็ไม่ต้องตกใจ คุณสามารถสร้างไซต์แบบคงที่แทนได้ตลอดเวลาในขณะที่ยังคงใช้ประโยชน์จากคุณลักษณะของ Nuxt
เพื่อให้เข้าใจถึงศักยภาพของ Nuxt เรามาสร้างโครงการง่ายๆ กัน ซอร์สโค้ดสุดท้ายสำหรับโปรเจ็กต์นี้โฮสต์อยู่บน GitHub หากคุณต้องการดู หรือดูเวอร์ชันจริงที่สร้างโดยใช้ nuxt generate
และโฮสต์บน Netlify
การสร้างโครงการ Nuxt
ในการเริ่มต้น ลองใช้ตัวสร้างโปรเจ็กต์ Vue ชื่อ vue-cli
เพื่อสร้างโปรเจ็กต์ตัวอย่างอย่างรวดเร็ว:
# install vue-cli globally npm install -g vue-cli # create a project using a nuxt template vue init nuxt-community/starter-template my-nuxt-project
หลังจากผ่านสองตัวเลือกแล้ว การดำเนินการนี้จะสร้างโปรเจ็กต์ภายในโฟลเดอร์ my-nuxt-project
หรืออะไรก็ตามที่คุณระบุ จากนั้นเราเพียงแค่ต้องติดตั้งการพึ่งพาและเรียกใช้เซิร์ฟเวอร์:
cd my-nuxt-project npm install # Or yarn npm run dev
เราจะไปที่นั่น. เปิดเบราว์เซอร์ของคุณไปที่ localhost:3000
และโปรเจ็กต์ของคุณควรจะทำงาน ไม่แตกต่างจากการสร้างโครงการ Vue Webpack มากนัก อย่างไรก็ตาม เมื่อเราดูโครงสร้างที่แท้จริงของแอป ก็ไม่มีอะไรมาก โดยเฉพาะอย่างยิ่งเมื่อเทียบกับเทมเพลต Vue Webpack
การดูใน package.json
ยังแสดงให้เห็นว่าเรามีการพึ่งพาเดียวคือ Nuxt เอง เนื่องจาก Nuxt แต่ละเวอร์ชันได้รับการปรับแต่งให้ทำงานกับ Vue, Vue-router และ Vuex เวอร์ชันเฉพาะ และรวมเข้าด้วยกันเพื่อคุณ
นอกจากนี้ยังมีไฟล์ nuxt.config.js
ที่รูทโปรเจ็กต์ สิ่งนี้ช่วยให้คุณปรับแต่งคุณสมบัติมากมายที่ Nuxt มีให้ โดยค่าเริ่มต้น จะตั้งค่าแท็กส่วนหัว สีของแถบการโหลด และกฎ ESLint สำหรับคุณ หากคุณต้องการดูว่าคุณสามารถกำหนดค่าอะไรได้บ้าง นี่คือเอกสารประกอบ เราจะกล่าวถึงตัวเลือกบางอย่างในบทความนี้
ไดเร็กทอรีเหล่านั้นมีความพิเศษอย่างไร?
เค้าโครงโครงการ
หากคุณเรียกดูไดเร็กทอรีที่สร้างขึ้น ไดเร็กทอรีทั้งหมดจะมี Readme ระบุข้อมูลสรุปโดยย่อว่ามีอะไรอยู่ในไดเร็กทอรีนั้นและมักจะมีลิงก์ไปยังเอกสาร
นี่เป็นข้อดีอย่างหนึ่งของการใช้ Nuxt: โครงสร้างเริ่มต้นสำหรับแอปพลิเคชันของคุณ นักพัฒนา front-end ที่ดีคนใดจะจัดโครงสร้างแอปพลิเคชันที่คล้ายคลึงกัน แต่มีแนวคิดที่แตกต่างกัน มากมาย เกี่ยวกับโครงสร้าง และเมื่อทำงานในทีม บางครั้งก็จะต้องพูดถึงหรือเลือกโครงสร้างนี้อย่างหลีกเลี่ยงไม่ได้ Nuxt มอบสิ่งหนึ่งให้คุณ
Nuxt จะค้นหาไดเร็กทอรีบางตัวและสร้างแอปพลิเคชันของคุณขึ้นอยู่กับสิ่งที่พบ ลองตรวจสอบไดเร็กทอรีเหล่านี้ทีละรายการ
หน้า
นี่เป็นไดเร็กทอรี ที่จำเป็น เท่านั้น คอมโพเนนต์ Vue ใดๆ ในไดเร็กทอรีนี้จะถูกเพิ่มไปยัง vue-router
โดยอัตโนมัติตามชื่อไฟล์และโครงสร้างไดเร็กทอรี สะดวก มาก โดยปกติฉันจะมีไดเร็กทอรี Pages แยกต่างหากอยู่แล้วและต้องลงทะเบียนแต่ละส่วนประกอบเหล่านั้นด้วยตนเองในไฟล์เราเตอร์อื่น ไฟล์เราเตอร์นี้อาจซับซ้อนสำหรับโปรเจ็กต์ขนาดใหญ่และอาจต้องแยกไฟล์เพื่อรักษาความสามารถในการอ่าน Nuxt จะจัดการตรรกะทั้งหมดนี้ให้คุณแทน
เพื่อสาธิต เราสามารถสร้างคอมโพเนนต์ Vue ที่เรียกว่า about.vue
ภายในไดเร็กทอรี Pages มาเพิ่มเทมเพลตง่ายๆ เช่น:
<template> <h1>About Page</h1> </template>
เมื่อคุณบันทึก Nuxt จะสร้างเส้นทางให้คุณอีกครั้ง เมื่อเห็นว่าเราเรียกองค์ประกอบของเรา about.vue
หากคุณไปที่ /about
คุณจะเห็นองค์ประกอบนั้น เรียบง่าย.
มีชื่อไฟล์พิเศษอยู่หนึ่งชื่อ การตั้งชื่อไฟล์ index.vue
จะสร้างเส้นทางรูทสำหรับไดเร็กทอรีนั้น เมื่อสร้างโครงการขึ้น มีองค์ประกอบ index.vue
ในไดเรกทอรีหน้าซึ่งสัมพันธ์กับหน้าแรกหรือหน้า Landing Page ของเว็บไซต์ของคุณอยู่แล้ว (ในตัวอย่างการพัฒนา นี่จะเป็น localhost:3000
)
แล้วเส้นทางที่ลึกกว่านั้นล่ะ? ไดเร็กทอรีย่อยในไดเร็กทอรี Pages ช่วยจัดโครงสร้างเส้นทางของคุณ ดังนั้น หากเราต้องการดูหน้าผลิตภัณฑ์ เราสามารถจัดโครงสร้างไดเรกทอรี Pages ได้ดังนี้:
/pages --| /products ----| index.vue ----| view.vue
ตอนนี้ ถ้าเราไปที่ /products/view
เราจะเห็นส่วนประกอบ view.vue
ภายในไดเร็กทอรี products หากเราไปที่ /products
แทน เราจะเห็นส่วนประกอบ index.vue
ภายในไดเร็กทอรี products
คุณอาจจะถามว่าทำไมเราไม่สร้างแค่ส่วนประกอบ products.vue
ในไดเร็กทอรีเพจ เหมือนที่เราทำกับเพจ /about
คุณอาจคิดว่าผลลัพธ์จะเหมือนกัน แต่มีความแตกต่างระหว่างโครงสร้างทั้งสอง มาสาธิตสิ่งนี้โดยเพิ่มหน้าใหม่อีกหน้าหนึ่ง
สมมติว่าเราต้องการแยกหน้าเกี่ยวกับพนักงานแต่ละคน ตัวอย่างเช่น มาสร้างหน้าเกี่ยวกับให้ฉัน ควรอยู่ที่ /about/ben-jones
เริ่มแรก เราอาจลองจัดโครงสร้างไดเร็กทอรี Pages ดังนี้:
/pages --| about.vue --| /about ----| ben-jones.vue
เมื่อเราพยายามเข้าถึง /about/ben-jones
เราจะได้รับองค์ประกอบ about.vue
เหมือนกับ /about
เกิดอะไรขึ้นที่นี่?
ที่น่าสนใจคือ สิ่งที่ Nuxt กำลังทำอยู่คือการสร้าง เส้นทางที่ซ้อนกัน โครงสร้างนี้แนะนำว่าคุณต้องการเส้นทางถาวร /about
และทุกสิ่งภายในเส้นทางนั้นควรซ้อนอยู่ในพื้นที่มุมมองของตัวเอง ใน vue-router สิ่งนี้มีความหมายโดยการระบุส่วนประกอบ <router-view />
ภายในองค์ประกอบ about.vue
ใน Nuxt นี่เป็นแนวคิดเดียวกัน ยกเว้น แทนที่จะเป็น <router-view />
เราเพียงแค่ใช้ <nuxt />
มาอัปเดตองค์ประกอบ about.vue
ของเราเพื่ออนุญาตเส้นทางที่ซ้อนกัน:
<template> <div> <h1>About Page</h1> <nuxt /> </div> </template>
เมื่อเราไปที่ /about
เราได้รับองค์ประกอบ about.vue
ที่เรามีมาก่อนโดยมีเพียงชื่อ อย่างไรก็ตาม เมื่อเรานำทางไปยัง /about/ben-jones
เรามีชื่อ และ องค์ประกอบ ben-jones.vue
ที่แสดงในตำแหน่งที่ตัวยึดตำแหน่ง <nuxt/>
อยู่
นี่ไม่ใช่สิ่งที่เราต้องการในตอนแรก แต่แนวคิดในการมีหน้าเกี่ยวกับที่มีรายชื่อบุคคลที่เมื่อคลิกแล้วกรอกข้อมูลในส่วนต่างๆ ในหน้านั้นเป็นแนวคิดที่น่าสนใจ เลยปล่อยไว้อย่างที่เป็นอยู่ตอนนี้ . หากคุณต้องการตัวเลือกอื่น สิ่งที่เราจะทำคือปรับโครงสร้างไดเร็กทอรีของเราใหม่ เราแค่ต้องย้ายองค์ประกอบ about.vue
ภายในไดเร็กทอรี /about
และเปลี่ยนชื่อเป็น index.vue
ดังนั้นโครงสร้างที่ได้จะเป็น:
/pages --| /about ----| index.vue ----| ben-jones.vue
สุดท้าย สมมติว่าเราต้องการใช้พารามิเตอร์เส้นทางเพื่อดึงข้อมูลผลิตภัณฑ์เฉพาะ ตัวอย่างเช่น เราต้องการแก้ไขผลิตภัณฑ์โดยไปที่ /products/edit/64
โดยที่ 64 คือ product_id
เราสามารถทำได้ด้วยวิธีต่อไปนี้:
/pages --| /products ----| /edit ------| _product_id.vue
สังเกตเครื่องหมายขีดล่างที่ตอนต้นของคอมโพเนนต์ _product_id.vue
ซึ่งหมายถึงพารามิเตอร์เส้นทางซึ่งสามารถเข้าถึงได้จาก $route.params
หรือบนอ็อบเจ็กต์ params
ในบริบทของ Nuxt (เพิ่มเติมในภายหลัง) โปรดทราบว่าคีย์สำหรับพารามิเตอร์จะเป็นชื่อคอมโพเนนต์โดยไม่มีเครื่องหมายขีดล่างเริ่มต้น ในกรณีนี้คือ product_id
ดังนั้นให้พยายามทำให้ไม่ซ้ำกันภายในโปรเจ็กต์ ด้วยเหตุนี้ ใน _product_id.vue
เราจึงอาจมีลักษณะดังนี้:
<template> <h1>Editing Product {{ $route.params.product_id }}</h1> </template>
คุณสามารถเริ่มจินตนาการถึงเลย์เอาต์ที่ซับซ้อนมากขึ้น ซึ่งอาจเป็นเรื่องยากที่จะตั้งค่าโดยใช้ vue-router ตัวอย่างเช่น เราสามารถรวมทั้งหมดข้างต้นเป็นเส้นทางเช่น:
/pages --| /categories ----| /_category_id ------| products.vue ------| /products --------| _product_id.vue
ไม่ยากเกินไปที่จะให้เหตุผลว่า /categories/2/products/3
จะแสดงอะไร เราจะมีองค์ประกอบ products.vue
ที่มีองค์ประกอบ _product_id.vue
ที่ ซ้อนกัน โดยมีพารามิเตอร์เส้นทางสองรายการ: category_id
และ product_id
สิ่งนี้ง่ายกว่าที่จะให้เหตุผลมากกว่าการกำหนดค่าเราเตอร์ที่เทียบเท่ากัน
ขณะที่เราอยู่ในหัวข้อนี้ สิ่งหนึ่งที่ฉันมักจะทำในการกำหนดค่าเราเตอร์คือการตั้งค่าตัวป้องกันเราเตอร์ เนื่องจาก Nuxt กำลังสร้างเราเตอร์ให้กับเรา จึงสามารถทำได้บนส่วนประกอบด้วย beforeRouteEnter
หากคุณต้องการตรวจสอบพารามิเตอร์ของเส้นทาง Nuxt จะจัดเตรียมวิธีการส่วนประกอบที่เรียกว่า validate
ดังนั้น หากคุณต้องการตรวจสอบว่า product_id
เป็นตัวเลขก่อนที่จะพยายามแสดงส่วนประกอบ คุณจะต้องเพิ่มสิ่งต่อไปนี้ในแท็กสคริปต์ของ _product_id.vue
:
export default { validate ({ params }) { // Must be a number return /^\d+$/.test(params.product_id) } }
ตอนนี้ การนำทางไปยัง /categories/2/products/someproduct
someproduct
ผลลัพธ์เป็น 404 เนื่องจากบางผลิตภัณฑ์ไม่ใช่ตัวเลขที่ถูกต้อง
นั่นคือทั้งหมดสำหรับไดเร็กทอรี Pages การเรียนรู้วิธีจัดโครงสร้างเส้นทางของคุณอย่างเหมาะสมในไดเร็กทอรีนี้เป็นสิ่งสำคัญ ดังนั้นการใช้เวลาเพียงเล็กน้อยในตอนแรกจึงสำคัญต่อการใช้ประโยชน์สูงสุดจาก Nuxt หากคุณกำลังมองหาภาพรวมโดยย่อ การอ้างอิงเอกสารสำหรับการกำหนดเส้นทางจะเป็นประโยชน์เสมอ
หากคุณกังวลว่าจะไม่สามารถควบคุมเราเตอร์ได้ ก็อย่ากังวลไป การตั้งค่าเริ่มต้นนี้ใช้งานได้ดีสำหรับโครงการที่หลากหลาย หากมีโครงสร้างที่ดี อย่างไรก็ตาม มีบางกรณีที่คุณอาจต้องเพิ่มเส้นทางไปยังเราเตอร์มากกว่าที่ Nuxt จะสร้างให้คุณโดยอัตโนมัติหรือปรับโครงสร้างใหม่ Nuxt มีวิธีปรับแต่งอินสแตนซ์ของเราเตอร์ในการกำหนดค่า ซึ่งช่วยให้คุณสามารถเพิ่มเส้นทางใหม่และกำหนดเส้นทางที่สร้างขึ้นเองได้ คุณยังสามารถแก้ไขฟังก์ชันการทำงานหลักของอินสแตนซ์เราเตอร์ ซึ่งรวมถึงตัวเลือกพิเศษที่เพิ่มโดย Nuxt ดังนั้น หากคุณพบเคสขอบ คุณยังคงมีความยืดหยุ่นในการค้นหาโซลูชันที่เหมาะสม
เก็บ
Nuxt สามารถสร้างร้านค้า Vuex ของคุณตามโครงสร้างของไดเร็กทอรี store คล้ายกับไดเร็กทอรี Pages หากคุณไม่ต้องการร้านค้า ให้ลบไดเร็กทอรีออก มีสองโหมดสำหรับร้านค้า คลาสสิก และ โมดูล
Classic ต้องการให้ คุณมีไฟล์ index.js
ในไดเร็กทอรีร้านค้า คุณต้องส่งออกฟังก์ชันที่ส่งคืนอินสแตนซ์ Vuex:
import Vuex from 'vuex' const createStore = () => { return new Vuex.Store({ state: ..., mutations: ..., actions: ... }) } export default createStore
สิ่งนี้ช่วยให้คุณสร้างร้านค้าได้ตามที่คุณต้องการ เหมือนกับการใช้ Vuex ในโครงการ Vue ปกติ
โหมดโมดูลยัง ต้องการให้ คุณสร้างไฟล์ index.js
ในไดเร็กทอรีร้านค้า อย่างไรก็ตาม ไฟล์นี้จำเป็นต้องส่งออกสถานะรูท/การกลายพันธุ์/การดำเนินการสำหรับร้านค้า Vuex ของคุณเท่านั้น ตัวอย่างด้านล่างระบุสถานะรูทว่าง:
export const state = () => ({})
จากนั้น แต่ละไฟล์ในไดเร็กทอรีร้านค้าจะถูกเพิ่มไปยังร้านค้าในเนมสเปซหรือโมดูลของตัวเอง ตัวอย่างเช่น มาสร้างที่ไหนสักแห่งเพื่อจัดเก็บผลิตภัณฑ์ปัจจุบัน หากเราสร้างไฟล์ชื่อ product.js
ในไดเร็กทอรีร้านค้า จากนั้นส่วนเนมสเปซของร้านค้าจะมีให้ที่ $store.product
ต่อไปนี้คือตัวอย่างง่ายๆ ว่าไฟล์นั้นมีลักษณะอย่างไร:
export const state = () => ({ _id: 0, title: 'Unknown', price: 0 }) export const actions = { load ({ commit }) { setTimeout( commit, 1000, 'update', { _id: 1, title: 'Product', price: 99.99 } ) } } export const mutations = { update (state, product) { Object.assign(state, product) } }
setTimeout
ในการโหลดจะจำลองการเรียก API บางประเภท ซึ่งจะอัปเดตร้านค้าด้วยการตอบสนอง ในกรณีนี้จะใช้เวลาหนึ่งวินาที ลองใช้ในหน้า products/view
:
<template> <div> <h1>View Product {{ product._id }}</h1> <p>{{ product.title }}</p> <p>Price: {{ product.price }}</p> </div> </template> <script> import { mapState } from 'vuex' export default { created () { this.$store.dispatch('product/load') }, computed: { ...mapState(['product']) } } </script>
ข้อควรทราบบางประการ: ในที่นี้ เรากำลังเรียกใช้ API ปลอมของเราเมื่อมีการสร้างส่วนประกอบ คุณจะเห็นว่า product/load
ที่เราจัดส่งมีการกำหนดเนมสเปซภายใต้ผลิตภัณฑ์ สิ่งนี้ทำให้ชัดเจนว่าเรากำลังติดต่อกับส่วนใดของร้านค้า จากนั้น โดยการแมปสถานะกับคุณสมบัติที่คำนวณในพื้นที่ เราก็สามารถใช้มันในเทมเพลตของเราได้อย่างง่ายดาย
มีปัญหา: เราเห็นสถานะเดิมเป็นวินาทีในขณะที่ API ทำงาน ต่อมา เราจะใช้โซลูชันที่ Nuxt จัดหาให้เพื่อแก้ไขปัญหานี้ (เรียกว่า fetch
)
เพื่อเน้นเรื่องนี้อีกครั้ง เราไม่ต้อง npm install vuex
เพราะมันรวมอยู่ในแพ็คเกจ Nuxt แล้ว เมื่อคุณเพิ่มไฟล์ index.js
ลงในไดเร็กทอรีร้านค้า เมธอดทั้งหมดจะถูกเปิดขึ้นมาให้คุณ โดยอัตโนมัติ
นั่นคือไดเร็กทอรีหลักสองไดเร็กทอรีอธิบาย; ที่เหลือง่ายกว่ามาก
ส่วนประกอบ
ไดเร็กทอรี Components มีไว้เพื่อบรรจุส่วนประกอบที่นำกลับมาใช้ใหม่ได้ เช่น แถบนำทาง แกลเลอรีรูปภาพ การแบ่งหน้า ตารางข้อมูล ฯลฯ เมื่อเห็นว่าส่วนประกอบในไดเร็กทอรี Pages ถูกแปลงเป็นเส้นทาง คุณจำเป็นต้องมีที่อื่นเพื่อจัดเก็บส่วนประกอบประเภทนี้ ส่วนประกอบเหล่านี้สามารถเข้าถึงได้ในเพจหรือส่วนประกอบอื่นๆ โดยการนำเข้า:
import ComponentName from ~/components/ComponentName.vue
ทรัพย์สิน
ข้อมูลนี้มีเนื้อหาที่ไม่ได้คอมไพล์และเกี่ยวข้องกับการโหลดและประมวลผลไฟล์ของ Webpack มากกว่าวิธีการทำงานของ Nuxt หากคุณสนใจ ฉันแนะนำให้อ่านคู่มือใน Readme
คงที่
ไฟล์นี้มีไฟล์สแตติกซึ่งถูกแมปกับไดเร็กทอรีรากของไซต์ของคุณ ตัวอย่างเช่น การวางรูปภาพชื่อ logo.png ในไดเร็กทอรีนี้จะทำให้ใช้งานได้ที่ /logo.png
วิธีนี้เหมาะสำหรับไฟล์เมตา เช่น robots.txt, favicon.ico และไฟล์อื่นๆ ที่คุณต้องการให้พร้อมใช้งาน
เลย์เอาต์
โดยปกติ ในโปรเจ็กต์ Vue คุณมีองค์ประกอบรูทบางประเภท ซึ่งปกติเรียกว่า App.vue
นี่คือที่ที่คุณสามารถตั้งค่าเลย์เอาต์แอป (โดยปกติเป็นแบบสแตติก) ซึ่งอาจรวมถึงแถบนำทาง ส่วนท้าย และพื้นที่เนื้อหาสำหรับ vue-router ของคุณ เลย์เอาต์ default
ทำอย่างนั้นและจัดเตรียมไว้ให้คุณในโฟลเดอร์เลย์เอาต์ ในขั้นต้น สิ่งที่มีคือ div ที่มีองค์ประกอบ <nuxt />
(ซึ่งเทียบเท่ากับ <router-view />
) แต่สามารถจัดรูปแบบได้ตามที่คุณต้องการ ตัวอย่างเช่น ฉันได้เพิ่มแถบนำทางอย่างง่ายให้กับโครงการตัวอย่างสำหรับการนำทางรอบๆ หน้าสาธิตต่างๆ

คุณอาจต้องการมีเลย์เอาต์ที่แตกต่างกันสำหรับบางส่วนของแอพของคุณ บางทีคุณอาจมี CMS หรือแผงผู้ดูแลระบบที่ดูแตกต่างออกไป ในการแก้ปัญหานี้ ให้สร้างเลย์เอาต์ใหม่ในไดเร็กทอรี Layouts ตัวอย่างเช่น มาสร้างเค้าโครง admin-layout.vue
ซึ่งมีแท็กส่วนหัวพิเศษและไม่มีแถบนำทาง:
<template> <div> <h1>Admin Layout</h1> <nuxt /> </div> </template>
จากนั้น เราสามารถสร้างหน้า admin.vue
ในไดเร็กทอรี Pages และใช้คุณสมบัติที่ Nuxt ให้มา ซึ่งเรียกว่า layout
ย์เอาต์เพื่อระบุชื่อ (เป็นสตริง) ของเลย์เอาต์ที่เราต้องการใช้สำหรับส่วนประกอบนั้น:
<template> <h1>Admin Page</h1> </template> <script> export default { layout: 'admin-layout' } </script>
นั่นคือทั้งหมดที่มีให้ ส่วนประกอบของเพจจะใช้เลย์เอาต์ default
เว้นแต่จะระบุไว้ แต่เมื่อคุณไปที่ /admin
ตอนนี้จะใช้เลย์เอา admin-layout.vue
แน่นอน เลย์เอาต์นี้สามารถใช้ร่วมกันได้ในหลายหน้าจอของผู้ดูแลระบบหากคุณต้องการ สิ่งสำคัญอย่างหนึ่งที่ต้องจำไว้คือ เลย์เอาต์ต้องมีองค์ประกอบ <nuxt />
มีสิ่งสุดท้ายที่ควรทราบเกี่ยวกับเลย์เอาต์ คุณอาจสังเกตเห็นขณะทำการทดลองว่าหากคุณพิมพ์ URL ที่ไม่ถูกต้อง คุณจะเห็นหน้าข้อผิดพลาด อันที่จริง หน้าแสดงข้อผิดพลาดนี้เป็นอีกรูปแบบหนึ่ง Nuxt มีเลย์เอาต์ข้อผิดพลาดของตัวเอง (ซอร์สโค้ดที่นี่) แต่ถ้าคุณต้องการแก้ไข เพียงแค่สร้างเลย์เอา error.vue
และจะใช้สิ่งนั้นแทน ข้อแม้ที่นี่คือ รูปแบบข้อผิดพลาดต้องไม่มีองค์ประกอบ <nuxt />
คุณจะสามารถเข้าถึงออบเจ็กต์ error
บนส่วนประกอบด้วยข้อมูลพื้นฐานที่จะแสดง (สิ่งนี้ถูกพิมพ์ออกมาในเทอร์มินัลที่รัน Nuxt หากคุณต้องการตรวจสอบ)
มิดเดิลแวร์
มิดเดิลแวร์เป็นฟังก์ชันที่สามารถดำเนินการได้ก่อนที่จะแสดงหน้าหรือเค้าโครง มีเหตุผลหลายประการที่คุณอาจต้องการทำเช่นนั้น การป้องกันเส้นทางเป็นการใช้งานยอดนิยมที่คุณสามารถตรวจสอบร้านค้า Vuex สำหรับการเข้าสู่ระบบที่ถูกต้องหรือตรวจสอบพารามิเตอร์บางอย่าง (แทนที่จะใช้วิธี validate
บนส่วนประกอบเอง) โปรเจ็กต์หนึ่งที่ฉันทำงานบนมิดเดิลแวร์เมื่อเร็วๆ นี้เพื่อสร้างเบรดครัมบ์แบบไดนามิกตามเส้นทางและพารามิเตอร์
ฟังก์ชันเหล่านี้สามารถเป็นแบบอะซิงโครนัสได้ โปรดใช้ความระมัดระวัง เนื่องจากจะไม่มีการแสดงข้อมูลใดๆ แก่ผู้ใช้จนกว่ามิดเดิลแวร์จะได้รับการแก้ไข พวกเขายังสามารถเข้าถึงบริบทของ Nuxt ซึ่งฉันจะอธิบายในภายหลัง
ปลั๊กอิน
ไดเร็กทอรีนี้อนุญาตให้คุณลงทะเบียนปลั๊กอิน Vue ก่อนสร้างแอปพลิเคชัน ซึ่งช่วยให้สามารถแชร์ปลั๊กอินทั่วทั้งแอปของคุณบนอินสแตนซ์ Vue และสามารถเข้าถึงได้ในทุกองค์ประกอบ
ปลั๊กอินหลักส่วนใหญ่มีเวอร์ชัน Nuxt ที่สามารถลงทะเบียนกับอินสแตนซ์ Vue ได้อย่างง่ายดายโดยทำตามเอกสารของพวกเขา อย่างไรก็ตาม จะมีบางสถานการณ์ที่คุณจะพัฒนาปลั๊กอินหรือจำเป็นต้องปรับเปลี่ยนปลั๊กอินที่มีอยู่เพื่อจุดประสงค์นี้ ตัวอย่างที่ฉันยืมมาจากเอกสารแสดงวิธีการทำสิ่งนี้สำหรับ vue-notifications
ขั้นแรกเราต้องติดตั้งแพ็คเกจ:
npm install vue-notifications --save
จากนั้นสร้างไฟล์ในไดเร็กทอรีปลั๊กอินที่เรียกว่า vue-notifications.js
และรวมสิ่งต่อไปนี้:
import Vue from 'vue' import VueNotifications from 'vue-notifications' Vue.use(VueNotifications)
คล้ายกันมากกับวิธีลงทะเบียนปลั๊กอินในสภาพแวดล้อม Vue ปกติ จากนั้นแก้ไขไฟล์ nuxt.config.js
ที่รูทโปรเจ็กต์ของคุณ และเพิ่มรายการต่อไปนี้ในอ็อบเจ็กต์ module.exports:
plugins: ['~/plugins/vue-notifications']
แค่นั้นแหละ. ตอนนี้คุณสามารถใช้ vue-notifications
ทั่วทั้งแอปของคุณ ตัวอย่างนี้คือที่ /plugin
ในโครงการตัวอย่าง
เพื่อให้สรุปโครงสร้างไดเร็กทอรีสมบูรณ์ อาจดูเหมือนมีอะไรให้เรียนรู้มากมาย แต่ถ้าคุณกำลังพัฒนาแอป Vue แสดงว่าคุณได้ตั้งค่าตรรกะแบบเดียวกันแล้ว Nuxt ช่วยในการสรุปการตั้งค่าและช่วยให้คุณมุ่งเน้นที่การสร้าง
Nuxt ทำมากกว่าช่วยในการพัฒนาแม้ว่า มันเพิ่ม พลัง ให้ส่วนประกอบของคุณโดยให้ฟังก์ชันพิเศษ
ส่วนประกอบซุปเปอร์ชาร์จของ Nuxt
เมื่อฉันเริ่มค้นคว้า Nuxt ครั้งแรก ฉันยังคงอ่านเกี่ยวกับวิธีการที่องค์ประกอบของหน้าถูก อัด มากเกินไป ฟังดูดีมาก แต่ก็ไม่ชัดเจนในทันทีว่านั่นหมายถึงอะไรและประโยชน์ที่ได้รับ
ความหมายคือองค์ประกอบของหน้าทั้งหมดมีวิธีการเพิ่มเติมที่แนบมากับองค์ประกอบเหล่านี้ ซึ่ง Nuxt สามารถใช้เพื่อให้มีฟังก์ชันการทำงานเพิ่มเติม อันที่จริง เราเคยเห็นสิ่งเหล่านี้ก่อนหน้านี้แล้วเมื่อเราใช้วิธี validate
เพื่อตรวจสอบพารามิเตอร์และเปลี่ยนเส้นทางผู้ใช้หากไม่ถูกต้อง
สองสิ่งหลักที่ใช้ในโปรเจ็กต์ Nuxt จะเป็น asyncData
และวิธี fetch
แนวคิดทั้งสองมีความคล้ายคลึงกันมาก โดยจะทำงาน แบบอะซิงโครนัส ก่อนที่จะสร้างส่วนประกอบ และสามารถใช้เพื่อเติมข้อมูลของส่วนประกอบและที่จัดเก็บ พวกเขายังเปิดใช้งานเพจเพื่อแสดงผลอย่างสมบูรณ์บนเซิร์ฟเวอร์ก่อนที่จะส่งไปยังไคลเอนต์ แม้ว่าเราจะต้องรอฐานข้อมูลหรือการเรียก API
asyncData
และ fetch
ต่างกันอย่างไร
-
asyncData
ใช้เพื่อเติมข้อมูลขององค์ประกอบหน้า เมื่อคุณส่งคืนอ็อบเจ็กต์ ออบเจ็กต์จะถูกรวมเข้ากับเอาต์พุตของdata
ก่อนแสดงผล - การ
fetch
ใช้เพื่อเติม Vuex Store หากคุณคืนสัญญา Nuxt จะรอจนกว่าจะได้รับการแก้ไขก่อนที่จะแสดงผล
เลยนำสิ่งเหล่านี้ไปใช้ให้เกิดประโยชน์ จำได้ไหมว่าก่อนหน้านี้ในหน้า /products/view
เรามีปัญหาที่สถานะเริ่มต้นของร้านค้าถูกแสดงชั่วครู่ในขณะที่ทำการเรียก API ปลอมของเรา วิธีหนึ่งในการแก้ไขปัญหานี้คือการเก็บบูลีนไว้ที่ส่วนประกอบหรือใน Store เช่น loading = true
จากนั้นแสดงส่วนประกอบการโหลดในขณะที่การเรียก API เสร็จสิ้น หลังจากนั้นเราจะตั้งค่า loading = false
และแสดงข้อมูล
ให้ใช้การ fetch
เพื่อเติมข้อมูลใน Store ก่อนแสดงผลแทน ในหน้าใหม่ที่ชื่อว่า /products/view-async
ให้เปลี่ยนวิธีการที่ created
เพื่อ fetch
; ที่ควรจะทำงานใช่มั้ย?
export default { fetch () { // Unfortunately the below line throws an error // because 'this.$store' is undefined... this.$store.dispatch('product/load') }, computed: {...} }
ประเด็นสำคัญ: เมธอด “ซูเปอร์ชาร์จ” เหล่า this
ทำงาน ก่อน สร้างส่วนประกอบ จึงไม่ชี้ไปที่ส่วนประกอบและไม่สามารถเข้าถึงได้ แล้วเราจะเข้าถึง Store ที่นี่ได้อย่างไร?
บริบท API
แน่นอนว่ามีทางแก้ ในวิธีการทั้งหมดของ Nuxt คุณจะได้รับอาร์กิวเมนต์ (โดยปกติเป็นอาร์กิวเมนต์แรก) ที่มีอ็อบเจ็กต์ที่มีประโยชน์อย่างยิ่งที่เรียกว่าบริบท นี่คือทุกสิ่งที่คุณจำเป็นต้องอ้างอิงถึงในแอป หมายความว่าเราไม่จำเป็นต้องรอให้ Vue สร้างข้อมูลอ้างอิงเหล่านั้นบนส่วนประกอบก่อน
ฉันขอแนะนำให้ตรวจสอบเอกสารบริบทเพื่อดูว่ามีอะไรบ้าง สิ่งที่มีประโยชน์บางอย่างคือ app
ที่คุณสามารถเข้าถึงปลั๊กอินทั้งหมดของคุณ redirect
ซึ่งสามารถใช้เพื่อเปลี่ยนเส้นทาง error
ในการแสดงหน้าข้อผิดพลาด และบางส่วนที่อธิบายตนเองได้ เช่น route
, query
และ store
ดังนั้น ในการเข้าถึง Store เราสามารถทำลายบริบทและแยก Store ออกจากมันได้ นอกจากนี้เรายังต้องแน่ใจว่าเราคืนสัญญาเพื่อให้ Nuxt สามารถรอให้แก้ไขได้ก่อนที่จะแสดงผลส่วนประกอบ ดังนั้นเราจึงจำเป็นต้องทำการปรับเปลี่ยนเล็กน้อยสำหรับการกระทำใน Store ของเราด้วย
// Component export default { fetch ({ store }) { return store.dispatch('product/load') }, computed: {...} } // Store Action load ({ commit }) { return new Promise(resolve => { setTimeout(() => { commit('update', { _id: 1, title: 'Product', price: 99.99 }) resolve() }, 1000) }) }
คุณสามารถใช้ async/await หรือวิธีอื่นๆ ขึ้นอยู่กับรูปแบบการเข้ารหัสของคุณ แต่แนวคิดก็เหมือนกัน—เรากำลังบอกให้ Nuxt ตรวจสอบให้แน่ใจว่าการเรียก API เสร็จสิ้น และ Store ได้รับการอัปเดตพร้อมผลลัพธ์ ก่อน ที่จะลองแสดงผลส่วนประกอบ หากคุณลองไปที่ /products/view-async
คุณจะไม่เห็นเนื้อหาที่ผลิตภัณฑ์อยู่ในสถานะเริ่มต้น
คุณสามารถจินตนาการได้ว่าสิ่งนี้มีประโยชน์เพียงใดในแอพ Vue ใด ๆ แม้จะไม่มี SSR บริบทยังใช้ได้กับ มิดเดิลแวร์ทั้งหมด เช่นเดียวกับวิธี Nuxt อื่น ๆ เช่น NuxtServerInit
ซึ่งเป็นการดำเนินการกับร้านค้าพิเศษที่ทำงานก่อนที่ Store จะเริ่มต้น (ตัวอย่างอยู่ในหัวข้อถัดไป)
ข้อควรพิจารณาเมื่อใช้SSR
ฉันแน่ใจว่าหลายคน (รวมตัวเองด้วย) ที่เริ่มใช้เทคโนโลยีเช่น Nuxt ในขณะที่ปฏิบัติต่อมันเหมือนโครงการ Vue อื่น ๆ ในที่สุดก็ชนเข้ากับกำแพงซึ่งสิ่งที่เรารู้ว่าปกติจะใช้งานไม่ได้ใน Nuxt เมื่อมีการบันทึกข้อแม้เหล่านี้มากขึ้น จะง่ายกว่าที่จะเอาชนะ แต่สิ่งสำคัญที่ควรพิจารณาเมื่อเริ่มดีบักคือไคลเอนต์และเซิร์ฟเวอร์เป็นสองเอนทิตีที่แยกจากกัน
เมื่อคุณเข้าถึงหน้าในขั้นต้น คำขอจะถูกส่งไปยัง Nuxt เซิร์ฟเวอร์จะสร้างหน้านั้นและส่วนที่เหลือของแอปให้มากที่สุด จากนั้นเซิร์ฟเวอร์จะส่งถึงคุณ จากนั้นลูกค้ามีหน้าที่รับผิดชอบในการนำทางและโหลดชิ้นส่วนตามที่ต้องการ
เราต้องการให้เซิร์ฟเวอร์ทำงานให้มากที่สุดก่อน แต่บางครั้งเซิร์ฟเวอร์ก็ไม่สามารถเข้าถึงข้อมูลที่ต้องการได้ ซึ่งส่งผลให้งานถูกทำให้เสร็จในฝั่งไคลเอ็นต์แทน หรือแย่กว่านั้น เมื่อเนื้อหาสุดท้ายที่นำเสนอโดยไคลเอนต์แตกต่างจากที่เซิร์ฟเวอร์คาดหวัง ลูกค้าจะได้รับคำสั่งให้สร้างใหม่ตั้งแต่ต้น นี่เป็นข้อบ่งชี้สำคัญว่ามีบางอย่างผิดปกติกับตรรกะของแอปพลิเคชัน โชคดีที่มีข้อผิดพลาดเกิดขึ้นในคอนโซลของเบราว์เซอร์ (ในโหมดการพัฒนา) หากสิ่งนี้เริ่มเกิดขึ้น
มาดูตัวอย่างวิธีแก้ปัญหาทั่วไป การจัดการเซสชัน ลองนึกภาพว่าคุณมีแอป Vue ที่คุณสามารถเข้าสู่ระบบบัญชีได้ และเซสชันของคุณจะถูกจัดเก็บโดยใช้โทเค็น (เช่น JWT) ซึ่งคุณตัดสินใจที่จะเก็บไว้ใน localStorage
เมื่อคุณเข้าถึงไซต์ในตอนแรก คุณต้องการตรวจสอบสิทธิ์โทเค็นนั้นกับ API ซึ่งจะส่งคืนข้อมูลผู้ใช้พื้นฐานบางอย่างหากถูกต้อง และใส่ข้อมูลนั้นใน Store
หลังจากอ่านเอกสารของ Nuxt คุณจะเห็นว่ามีวิธีการที่เรียกว่า NuxtServerInit
ที่สะดวก ซึ่งช่วยให้คุณเติมข้อมูลใน Store แบบอะซิงโครนัสได้ครั้งเดียวในการโหลดครั้งแรก นั่นฟังดูสมบูรณ์แบบ! ดังนั้น คุณจึงสร้างโมดูลผู้ใช้ของคุณใน Store และเพิ่มการดำเนินการที่เหมาะสมในไฟล์ index.js
ในไดเร็กทอรี Store:
export const actions = { nuxtServerInit ({ dispatch }) { // localStorage should work, right? const token = localStorage.getItem('token') if (token) return dispatch('user/load', token) } }
เมื่อคุณรีเฟรชหน้า คุณจะได้รับข้อผิดพลาด localStorage is not defined
เมื่อนึกถึงว่าสิ่งนี้เกิดขึ้นที่ไหน มันสมเหตุสมผลแล้ว เมธอดนี้รันบนเซิร์ฟเวอร์ มันไม่รู้ว่าอะไรถูกเก็บไว้ใน localStorage
บนไคลเอนต์ ที่จริงแล้ว มันไม่รู้ด้วยซ้ำว่า “localStorage” คืออะไร! นั่นไม่ใช่ตัวเลือก
แล้วทางออกคืออะไร? มีไม่กี่จริง คุณสามารถทำให้ไคลเอนต์เริ่มต้น Store แทนได้ แต่จบลงด้วยการสูญเสียประโยชน์ของ SSR เนื่องจากไคลเอนต์ลงเอยด้วยการทำงานทั้งหมด คุณสามารถตั้งค่าเซสชันบนเซิร์ฟเวอร์แล้วใช้เพื่อตรวจสอบสิทธิ์ผู้ใช้ แต่นั่นเป็นอีกชั้นหนึ่งที่ต้องตั้งค่า สิ่งที่คล้ายกับวิธีการ localStorage
มากที่สุดคือการใช้คุกกี้แทน
Nuxt มีสิทธิ์เข้าถึงคุกกี้เนื่องจากส่งพร้อมกับคำขอจากลูกค้าไปยังเซิร์ฟเวอร์ เช่นเดียวกับวิธี Nuxt อื่น ๆ nuxtServerInit
มีสิทธิ์เข้าถึงบริบท คราวนี้เป็นอาร์กิวเมนต์ที่สองเนื่องจากอาร์กิวเมนต์แรกสงวนไว้สำหรับร้านค้า ในบริบท เราสามารถเข้าถึงวัตถุ req
ซึ่งเก็บส่วนหัวและข้อมูลอื่น ๆ ทั้งหมดจากคำขอของลูกค้า (จะคุ้นเคยเป็นพิเศษหากคุณเคยใช้ Node.js)
ดังนั้นหลังจากเก็บโทเค็นไว้ในคุกกี้แทน (ในกรณีนี้เรียกว่า “โทเค็น”) ให้เข้าถึงบนเซิร์ฟเวอร์
import Cookie from 'cookie' export const actions = { nuxtServerInit ({ dispatch }, { req }) { const cookies = Cookie.parse(req.headers.cookie || '') const token = cookies['token'] || '' if (token) return dispatch('user/load', token) } }
วิธีแก้ปัญหาง่ายๆ แต่อาจไม่ชัดเจนในทันที เรียนรู้ที่จะคิดว่าการกระทำบางอย่างเกิดขึ้นที่ใด (ไคลเอนต์ เซิร์ฟเวอร์ หรือทั้งสองอย่าง) และสิ่งที่พวกเขาเข้าถึงได้นั้นต้องใช้เวลาพอสมควร แต่ประโยชน์ที่ได้รับก็คุ้มค่า
การปรับใช้
การปรับใช้กับ Nuxt นั้นง่ายมาก คุณสามารถสร้างแอป SSR แอปพลิเคชันหน้าเดียว หรือหน้าสแตติกได้โดยใช้โค้ดเบสเดียวกัน
แอปแสดงผลฝั่งเซิร์ฟเวอร์ (แอป SSR)
นี่อาจเป็นสิ่งที่คุณตั้งเป้าไว้เมื่อใช้ Nuxt แนวคิดพื้นฐานสำหรับการปรับใช้ที่นี่คือการรันกระบวนการ build
บนแพลตฟอร์มใดก็ตามที่คุณเลือกและตั้งค่าคอนฟิกบางส่วน ฉันจะใช้ตัวอย่าง Heroku จากเอกสาร:
ขั้นแรก ตั้งค่าสคริปต์สำหรับ Heroku ใน package.json
:
"scripts": { "dev": "nuxt", "build": "nuxt build", "start": "nuxt start", "heroku-postbuild": "npm run build" }
จากนั้นตั้งค่าสภาพแวดล้อม Heroku โดยใช้ heroku-cli
(คำแนะนำการตั้งค่าที่นี่:
# set Heroku variables heroku config:set NPM_CONFIG_PRODUCTION=false heroku config:set HOST=0.0.0.0 heroku config:set NODE_ENV=production # deploy git push heroku master
แค่นั้นแหละ. ตอนนี้แอป SSR Vue ของคุณพร้อมให้โลกได้เห็นแล้ว แพลตฟอร์มอื่นมีการตั้งค่าที่แตกต่างกัน แต่กระบวนการนี้คล้ายกัน วิธีการปรับใช้อย่างเป็นทางการที่แสดงอยู่ในปัจจุบันคือ:
- ตอนนี้
- Dokku (มหาสมุทรดิจิทัล)
- Nginx
แอปพลิเคชันหน้าเดียว (SPA)
หากคุณต้องการใช้ประโยชน์จากคุณลักษณะพิเศษบางอย่างที่ Nuxt มีให้ แต่หลีกเลี่ยงเซิร์ฟเวอร์ที่พยายามแสดงหน้า คุณสามารถปรับใช้เป็น SPA แทนได้
อันดับแรก เป็นการดีที่สุดที่จะทดสอบแอปพลิเคชันของคุณโดยไม่มี SSR เนื่องจากโดยค่าเริ่มต้น npm run dev
จะทำงานโดยเปิด SSR หากต้องการเปลี่ยนแปลง ให้แก้ไขไฟล์ nuxt.config.js
และเพิ่มตัวเลือกต่อไปนี้:
mode: 'spa',
ตอนนี้ เมื่อคุณเรียกใช้ npm run dev
SSR จะถูกปิดและแอปพลิเคชันจะทำงานเป็น SPA ให้คุณทดสอบ การตั้งค่านี้ยังช่วยให้แน่ใจว่าไม่มีการสร้างในอนาคตจะรวม SSR
หากทุกอย่างดูดี การปรับใช้จะเหมือนกับแอป SSR ทุกประการ เพียงจำไว้ว่าคุณต้องตั้งค่า mode: 'spa'
ก่อนเพื่อให้กระบวนการสร้างรู้ว่าคุณต้องการสปา
หน้าคงที่
หากคุณไม่ต้องการจัดการกับเซิร์ฟเวอร์เลย และต้องการสร้างเพจสำหรับใช้กับบริการโฮสติ้งแบบสแตติก เช่น Surge หรือ Netlify แทน ตัวเลือกนี้เป็นตัวเลือก จำไว้ว่าหากไม่มีเซิร์ฟเวอร์ คุณจะไม่สามารถเข้าถึง req
และ res
ในบริบทได้ ดังนั้นหากรหัสของคุณต้องอาศัยสิ่งนั้น ให้แน่ใจว่าได้ปรับให้เข้ากับมัน ตัวอย่างเช่น เมื่อสร้างโปรเจ็กต์ตัวอย่าง ฟังก์ชัน nuxtServerInit
จะแสดงข้อผิดพลาดเนื่องจากพยายามดึงโทเค็นจากคุกกี้ในส่วนหัวของคำขอ ในโปรเจ็กต์นี้ ไม่สำคัญเพราะว่าข้อมูลนั้นไม่ได้ถูกใช้ที่ไหนเลย แต่ในแอปพลิเคชันจริง จะต้องมีวิธีอื่นในการเข้าถึงข้อมูลนั้น
เมื่อจัดเรียงแล้ว การนำไปใช้งานก็ทำได้ง่าย สิ่งหนึ่งที่คุณอาจต้องเปลี่ยนก่อนคือการเพิ่มตัวเลือกเพื่อให้คำสั่ง nuxt generate
จะสร้างไฟล์ทางเลือกด้วย ไฟล์นี้จะแจ้งบริการโฮสติ้งเพื่อให้ Nuxt จัดการการกำหนดเส้นทางแทนบริการโฮสติ้ง ทำให้เกิดข้อผิดพลาด 404 โดยเพิ่มบรรทัดต่อไปนี้ใน nuxt.config.js
:
generate: { fallback: true },
นี่คือตัวอย่างการใช้ Netlify ซึ่งขณะนี้ยังไม่มีอยู่ในเอกสาร Nuxt โปรดจำไว้ว่าหากนี่เป็นครั้งแรกที่คุณใช้ netlify-cli
คุณจะได้รับแจ้งให้ตรวจสอบสิทธิ์:
# install netlify-cli globally npm install netlify-cli -g # generate the application (outputs to dist/ folder) npm run generate # deploy netlify deploy dist
มันง่ายอย่างนั้น! ดังที่กล่าวไว้ตอนต้นของบทความ มีเวอร์ชันของโครงการนี้ที่นี่ นอกจากนี้ยังมีเอกสารการใช้งานอย่างเป็นทางการสำหรับบริการดังต่อไปนี้:
- ไฟกระชาก
- GitHub Pages
เรียนรู้เพิ่มเติม
Nuxt กำลังอัปเดตอย่างรวดเร็ว และนี่เป็นเพียงคุณสมบัติบางส่วนที่มีให้เท่านั้น ฉันหวังว่าบทความนี้จะสนับสนุนให้คุณลองใช้และดูว่าจะช่วยปรับปรุงความสามารถของแอปพลิเคชัน Vue ของคุณหรือไม่ ช่วยให้คุณพัฒนาได้เร็วขึ้นและใช้ประโยชน์จากคุณลักษณะอันทรงพลังของมัน
หากคุณกำลังมองหาข้อมูลเพิ่มเติม อย่ามองข้ามลิงก์ทางการของ Nuxt:
- เอกสาร
- สนามเด็กเล่น
- GitHub
- คำถามที่พบบ่อย
Looking to up your JavaScript game? Try reading The Comprehensive Guide to JavaScript Design Patterns by fellow Toptaler Marko Mišura.