Nuxt.js를 사용하여 서버 측 렌더링된 Vue.js 앱 만들기
게시 됨: 2022-03-11Vue와 같은 JavaScript 프레임워크/라이브러리는 사이트를 탐색할 때 환상적인 사용자 경험을 제공할 수 있습니다. 대부분은 매번 서버에 요청을 보내지 않고도 페이지 콘텐츠를 동적으로 변경하는 방법을 제공합니다.
그러나 이 접근 방식에는 문제가 있습니다. 웹사이트를 처음 로드할 때 브라우저는 표시할 전체 페이지를 받지 못합니다. 대신 페이지를 구성하기 위한 많은 조각(HTML, CSS, 기타 파일)과 그것들을 함께 모으는 방법에 대한 지침(JavaScript 프레임워크/라이브러리) 이 모든 정보를 함께 모으는 데 상당한 시간이 걸립니다. 브라우저에 실제로 표시할 항목이 있기 전에. 그것은 평평한 책장과 함께 한 묶음의 책을 보내는 것과 같습니다. 먼저 책장을 만들고 책으로 채워야 합니다.
이에 대한 해결책은 현명합니다. 바로 표시할 수 있는 페이지를 만들 수 있는 프레임워크/라이브러리 버전을 서버 에 두십시오. 그런 다음 일부 책과 함께 기성품 책장을 보내는 것처럼 이 전체 페이지를 추가 변경을 수행하고 여전히 동적 페이지 콘텐츠(프레임워크/라이브러리)를 가질 수 있는 기능과 함께 브라우저로 보냅니다. 물론 책을 책장에 넣어야 하지만 즉시 사용할 수 있는 것이 있습니다.
어리석은 비유 외에도 많은 다른 이점이 있습니다. 예를 들어 회사 소개 페이지와 같이 거의 변경되지 않는 페이지는 사용자가 요청할 때마다 다시 만들 필요가 없습니다. 따라서 서버는 한 번 생성한 다음 나중에 사용할 수 있도록 캐시하거나 어딘가에 저장할 수 있습니다. 이러한 속도 향상은 미미해 보일 수 있지만 응답 시간이 밀리초(또는 그 이하)로 측정되는 환경에서는 모든 것이 중요합니다.
Vue 환경에서 SSR의 장점에 대해 더 자세히 알고 싶다면 SSR에 대한 Vue의 자체 기사를 확인해야 합니다. 이러한 결과를 얻기 위한 다양한 옵션이 있지만 Vue 팀에서도 권장하는 가장 인기 있는 옵션은 Nuxt입니다.
왜 Nuxt.js
Nuxt.js는 Next라는 인기 있는 React 라이브러리에 대한 SSR 구현을 기반으로 합니다. 이 디자인의 장점을 본 후 비슷한 구현이 Nuxt라는 Vue용으로 설계되었습니다. React+Next 조합에 익숙한 사람들은 애플리케이션의 디자인과 레이아웃에서 많은 유사점을 발견할 것입니다. 그러나 Nuxt는 Vue에 대한 강력하면서도 유연한 SSR 솔루션을 만들기 위해 Vue 관련 기능을 제공합니다.
Nuxt는 2018년 1월에 프로덕션 준비가 된 1.0 버전으로 업데이트되었으며 활발하고 잘 지원되는 커뮤니티의 일부입니다. 좋은 점 중 하나는 Nuxt를 사용하여 프로젝트를 빌드하는 것이 다른 Vue 프로젝트를 빌드하는 것과 다르지 않다는 것입니다. 사실, 짧은 시간에 잘 구조화된 코드베이스를 생성할 수 있는 많은 기능을 제공합니다.
주목해야 할 또 다른 중요한 점은 Nuxt가 SSR에 사용될 필요가 없다는 것 입니다. 범용 Vue.js 애플리케이션을 생성하기 위한 프레임워크로 승격되며 동일한 코드베이스를 사용하여 정적으로 생성된 Vue 애플리케이션을 생성하기 위한 명령( nuxt generate
)을 포함합니다. 따라서 SSR에 깊이 빠져드는 것이 두려운 경우 당황하지 마십시오. Nuxt의 기능을 계속 활용하면서 항상 대신 정적 사이트를 만들 수 있습니다.
Nuxt의 잠재력을 파악하기 위해 간단한 프로젝트를 만들어 보겠습니다. 이 프로젝트의 최종 소스 코드는 보고 싶은 경우 GitHub에서 호스팅되거나 nuxt generate
를 사용하여 생성되고 Netlify에서 호스팅되는 라이브 버전을 볼 수 있습니다.
Nuxt 프로젝트 만들기
시작하려면 vue-cli
라는 Vue 프로젝트 생성기를 사용하여 샘플 프로젝트를 빠르게 생성해 보겠습니다.
# 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 사용의 이점 중 하나입니다. 애플리케이션의 기본 구조입니다. 좋은 프론트엔드 개발자라면 누구나 이와 유사한 애플리케이션을 구성할 것이지만, 구조에 대한 다양한 아이디어가 있으며 팀으로 작업할 때 불가피하게 이 구조를 논의하거나 선택하는 데 시간이 소요됩니다. Nuxt는 하나를 제공합니다.
Nuxt는 특정 디렉토리를 찾고 찾은 내용에 따라 애플리케이션을 빌드합니다. 이 디렉토리를 하나씩 살펴보겠습니다.
페이지
이것은 유일한 필수 디렉토리입니다. 이 디렉토리의 모든 Vue 구성 요소는 파일 이름과 디렉토리 구조를 기반으로 vue-router
에 자동으로 추가됩니다. 이것은 매우 편리합니다. 일반적으로 어쨌든 별도의 Pages 디렉토리가 있고 다른 라우터 파일에 이러한 각 구성 요소를 수동으로 등록해야 합니다. 이 라우터 파일은 대규모 프로젝트의 경우 복잡해질 수 있으며 가독성을 유지하기 위해 분할이 필요할 수 있습니다. 대신 Nuxt가 이 모든 논리를 처리합니다.
시연하기 위해 Page 디렉토리 안에 about.vue
라는 Vue 구성 요소를 만들 수 있습니다. 다음과 같은 간단한 템플릿을 추가해 보겠습니다.
<template> <h1>About Page</h1> </template>
저장하면 Nuxt가 경로를 다시 생성합니다. 구성 요소를 about.vue
라고 부를 때 /about
으로 이동하면 해당 구성 요소가 표시되어야 합니다. 단순한.
특별한 파일 이름이 하나 있습니다. 파일 이름을 index.vue
로 지정하면 해당 디렉토리에 대한 루트 경로가 생성됩니다. 프로젝트가 생성되면 페이지 디렉토리에 이미 index.vue
구성 요소가 있어 사이트의 홈페이지 또는 방문 페이지와 관련이 있습니다. (개발 예제에서는 단순히 localhost:3000
입니다.)
더 깊은 경로는 어떻습니까? Pages 디렉토리의 하위 디렉토리는 경로를 구성하는 데 도움이 됩니다. 따라서 제품 보기 페이지가 필요한 경우 Pages 디렉토리를 다음과 같이 구성할 수 있습니다.
/pages --| /products ----| index.vue ----| view.vue
이제 /products/view
로 이동하면 제품 디렉토리 내부에 view.vue
구성 요소가 표시됩니다. 대신 /products
로 이동하면 제품 디렉토리 내부에 index.vue
구성 요소가 표시됩니다.
/about
페이지에서처럼 페이지 디렉토리에 products.vue
구성 요소를 생성하지 않은 이유를 물으실 수 있습니다. 결과는 같다고 생각할 수 있지만 두 구조 사이에는 차이가 있습니다. 다른 새 페이지를 추가하여 이를 시연해 보겠습니다.
각 직원에 대해 별도의 정보 페이지를 원한다고 가정해 보겠습니다. 예를 들어 나를 위한 정보 페이지를 만들어 보겠습니다. /about/ben-jones
있어야 합니다. 처음에는 Pages 디렉토리를 다음과 같이 구성할 수 있습니다.
/pages --| about.vue --| /about ----| ben-jones.vue
/about/ben-jones
액세스하려고 하면 대신 /about
과 동일한 about.vue
구성 요소를 얻습니다. 무슨 일이야?
흥미롭게도 Nuxt가 여기서 하는 일은 중첩된 경로 를 생성하는 것입니다. 이 구조는 영구적인 /about
경로를 원하고 해당 경로 내부의 모든 항목이 자체 보기 영역에 중첩되어야 함을 나타냅니다. vue-router에서 이는 about.vue
구성 요소 내부에 <router-view />
구성 요소를 지정하여 나타냅니다. 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
개체 또는 Nuxt 컨텍스트의 params
개체에서 액세스할 수 있는 경로 매개변수를 나타냅니다(자세한 내용은 나중에 설명). param의 키는 초기 밑줄이 없는 구성 요소 이름(이 경우 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
이 무엇을 표시할지 추론하는 것은 그리 어렵지 않습니다. 중첩된 _product_id.vue
구성 요소가 있는 products.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) } }
이제 someproduct
가 유효한 숫자가 아니기 때문에 /categories/2/products/someproduct
로 이동하면 404가 표시됩니다.
그것이 Pages 디렉토리에 대한 것입니다. 이 디렉토리에서 경로를 적절하게 구성하는 방법을 배우는 것은 필수적이므로 처음에 약간의 시간을 보내는 것이 Nuxt를 최대한 활용하는 데 중요합니다. 간단한 개요를 찾고 있다면 라우팅에 대한 문서를 참조하는 것이 항상 도움이 됩니다.
라우터를 제어하지 못하는 것이 걱정된다면 그러지 마십시오. 이 기본 설정은 잘 구성되어 있는 경우 다양한 프로젝트에 적합합니다. 그러나 Nuxt가 자동으로 생성하거나 재구성하는 것보다 더 많은 경로를 라우터에 추가해야 하는 경우가 있습니다. Nuxt는 구성에서 라우터 인스턴스를 사용자 지정하는 방법을 제공하여 새 경로를 추가하고 생성된 경로를 사용자 지정할 수 있습니다. Nuxt에서 추가한 추가 옵션을 포함하여 라우터 인스턴스의 핵심 기능을 편집할 수도 있습니다. 따라서 극단적인 경우가 발생하더라도 적절한 솔루션을 찾을 수 있는 유연성이 있습니다.
가게
Nuxt는 Pages 디렉토리와 유사한 store 디렉토리의 구조를 기반으로 Vuex 스토어를 구축할 수 있습니다. 저장소가 필요하지 않은 경우 디렉토리를 제거하면 됩니다. 스토어에는 Classic 및 Modules의 두 가지 모드가 있습니다.
Classic을 사용 하려면 store 디렉토리에 index.js
파일이 있어야 합니다. Vuex 인스턴스를 반환하는 함수를 내보내야 합니다.
import Vuex from 'vuex' const createStore = () => { return new Vuex.Store({ state: ..., mutations: ..., actions: ... }) } export default createStore
이를 통해 일반 Vue 프로젝트에서 Vuex를 사용하는 것처럼 원하는 대로 저장소를 만들 수 있습니다.
모듈 모드에서는 store 디렉토리에 index.js
파일을 생성 해야 합니다. 그러나 이 파일은 Vuex 저장소의 루트 상태/돌연변이/액션만 내보내면 됩니다. 아래 예에서는 빈 루트 상태를 지정합니다.
export const state = () => ({})
그런 다음 저장소 디렉터리의 각 파일은 자체 네임스페이스 또는 모듈의 저장소에 추가됩니다. 예를 들어 현재 제품을 저장할 위치를 생성해 보겠습니다. store 디렉토리에 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 호출을 시뮬레이션합니다. 이 경우 1초가 걸립니다. 이제 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
작업이 Product 아래에 네임스페이스임을 알 수 있습니다. 이것은 우리가 취급하는 상점의 섹션을 정확히 명확하게 합니다. 그런 다음 상태를 로컬 계산 속성에 매핑하여 템플릿에서 쉽게 사용할 수 있습니다.
문제가 있습니다. API가 실행되는 동안 잠시 원래 상태가 표시됩니다. 나중에 Nuxt에서 제공하는 솔루션을 사용하여 이를 수정합니다( fetch
라고 함).
이 점을 다시 강조하기 위해 vuex가 이미 Nuxt 패키지에 포함되어 있으므로 npm install vuex
가 없습니다. index.js
파일을 스토어 디렉토리에 추가하면 모든 메소드가 자동으로 열립니다.
이것이 설명된 주요 두 디렉토리입니다. 나머지는 훨씬 간단합니다.
구성품
Components 디렉토리는 탐색 모음, 이미지 갤러리, 페이지 매김, 데이터 테이블 등과 같은 재사용 가능한 구성 요소를 포함하기 위해 있습니다. Pages 디렉토리의 구성 요소가 경로로 변환되는 것을 볼 때 이러한 유형의 구성 요소를 저장할 다른 위치가 필요합니다. 이러한 구성 요소는 페이지 또는 다른 구성 요소를 가져와서 액세스할 수 있습니다.
import ComponentName from ~/components/ComponentName.vue
자산
여기에는 컴파일되지 않은 자산이 포함되며 Nuxt의 작동 방식보다는 Webpack이 파일을 로드하고 처리하는 방식과 더 관련이 있습니다. 관심이 있는 경우 Readme에서 가이드를 읽는 것이 좋습니다.
공전
여기에는 사이트의 루트 디렉터리에 매핑된 정적 파일이 포함됩니다. 예를 들어, 이 디렉토리에 logo.png라는 이미지를 /logo.png
에서 사용할 수 있습니다. 이것은 robots.txt, favicon.ico 및 기타 필요한 파일과 같은 메타 파일에 유용합니다.
레이아웃
일반적으로 Vue 프로젝트에는 일반적으로 App.vue
라고 하는 일종의 루트 구성 요소가 있습니다. 여기에서 탐색 모음, 바닥글 및 vue-router의 콘텐츠 영역을 포함할 수 있는 (일반적으로 정적) 앱 레이아웃을 설정할 수 있습니다. default
레이아웃은 정확히 그 작업을 수행하며 레이아웃 폴더에서 제공됩니다. 처음에는 <nuxt />
구성 요소( <router-view />
와 동일)가 있는 div만 있지만 원하는 대로 스타일을 지정할 수 있습니다. 예를 들어 다양한 데모 페이지를 탐색할 수 있도록 예제 프로젝트에 간단한 탐색 모음을 추가했습니다.

앱의 특정 섹션에 대해 다른 레이아웃을 원할 수 있습니다. 다르게 보이는 일종의 CMS 또는 관리자 패널이 있을 수 있습니다. 이 문제를 해결하려면 Layouts 디렉토리에 새 레이아웃을 만드십시오. 예를 들어 추가 헤더 태그만 있고 탐색 모음이 없는 admin-layout.vue
레이아웃을 만들어 보겠습니다.
<template> <div> <h1>Admin Layout</h1> <nuxt /> </div> </template>
그런 다음 Pages 디렉토리에 admin.vue
페이지를 만들고 layout
이라는 Nuxt에서 제공하는 속성을 사용하여 해당 구성 요소에 사용할 레이아웃의 이름(문자열으로)을 지정할 수 있습니다.
<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 인스턴스의 앱 전체에서 플러그인을 공유하고 모든 구성 요소에서 액세스할 수 있습니다.
대부분의 주요 플러그인에는 문서를 따라 Vue 인스턴스에 쉽게 등록할 수 있는 Nuxt 버전이 있습니다. 그러나 플러그인을 개발하거나 이 목적을 위해 기존 플러그인을 적용해야 하는 상황이 있습니다. 내가 문서에서 차용하는 예는 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를 처음 연구하기 시작했을 때 Page 구성 요소가 어떻게 과급 되는지에 대해 계속 읽었습니다. 그것은 훌륭하게 들렸지만 그것이 정확히 무엇을 의미하고 그것이 가져오는 이점이 무엇인지 즉시 명확하지 않았습니다.
이것이 의미하는 바는 모든 Page 구성 요소에는 Nuxt가 추가 기능을 제공하는 데 사용할 수 있는 추가 메서드가 첨부되어 있다는 것입니다. 사실, 우리는 이미 validate
메소드를 사용하여 매개변수를 확인하고 매개변수가 유효하지 않은 경우 사용자를 리디렉션할 때 이들 중 하나를 본 적이 있습니다.
Nuxt 프로젝트에서 사용되는 두 가지 주요 방법은 asyncData
및 fetch
메서드입니다. 둘 다 개념이 매우 유사하며 구성 요소가 생성되기 전에 비동기적 으로 실행되며 구성 요소 및 저장소의 데이터를 채우는 데 사용할 수 있습니다. 또한 일부 데이터베이스 또는 API 호출을 기다려야 하는 경우에도 클라이언트에 페이지를 보내기 전에 서버에서 페이지를 완전히 렌더링할 수 있습니다.
asyncData
와 fetch
의 차이점은 무엇입니까?
-
asyncData
는 Page 구성 요소의 데이터를 채우는 데 사용됩니다. 객체를 반환하면 렌더링 전에data
출력과 병합됩니다. -
fetch
는 Vuex Store를 채우는 데 사용됩니다. 약속을 반환하면 Nuxt는 렌더링 전에 해결될 때까지 기다립니다.
그럼 이것들을 잘 활용해보자. /products/view
페이지에서 가짜 API 호출이 수행되는 동안 상점의 초기 상태가 잠시 표시되는 문제가 있었던 것을 기억하십니까? 이 문제를 해결하는 한 가지 방법은 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
구성 요소에 액세스할 수 없습니다. 여기에서 스토어에 어떻게 액세스합니까?
컨텍스트 API
물론 해결책이 있습니다. Nuxt의 모든 메소드에는 Context라는 매우 유용한 객체가 포함된 인수(일반적으로 첫 번째)가 제공됩니다. 여기에는 앱 전체에서 참조해야 하는 모든 것이 있습니다. 즉, 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 또는 다른 방법을 사용할 수 있지만 개념은 동일합니다. 즉, 구성 요소 렌더링을 시도 하기 전에 API 호출이 완료되고 Store가 결과로 업데이트되도록 Nuxt에 지시하는 것입니다. /products/view-async
로 이동하려고 하면 제품이 초기 상태에 있는 플래시 콘텐츠를 볼 수 없습니다.
SSR이 없어도 모든 Vue 앱에서 이것이 얼마나 유용한지 상상할 수 있습니다. 컨텍스트는 스토어가 초기화되기 전에 실행되는 특별한 스토어 작업인 NuxtServerInit
와 같은 다른 Nuxt 메소드뿐만 아니라 모든 미들웨어 에서도 사용할 수 있습니다(이 예는 다음 섹션에 있습니다).
SSR 사용 시 고려 사항
다른 Vue 프로젝트처럼 다루면서 Nuxt와 같은 기술을 사용하기 시작한 많은 사람들(저 포함)이 결국 Nuxt에서는 일반적으로 작동한다고 알고 있던 것이 불가능해 보이는 벽에 부딪혔습니다. 이러한 주의 사항이 더 많이 문서화되면 극복하기가 더 쉬울 것이지만 디버그를 시작할 때 고려해야 할 주요 사항은 클라이언트와 서버가 두 개의 별도 엔터티라는 것입니다.
처음에 페이지에 액세스하면 Nuxt에 요청이 전송되고 서버는 해당 페이지와 나머지 앱을 최대한 많이 빌드한 다음 서버에서 이를 사용자에게 보냅니다. 그런 다음 탐색을 계속하고 필요할 때 청크를 로드하는 책임은 클라이언트에 있습니다.
우리는 서버가 가능한 한 많은 일을 먼저 하기를 원하지만 때로는 필요한 정보에 액세스할 수 없어 작업이 클라이언트 측에서 대신 수행되는 결과를 낳습니다. 또는 더 나쁜 것은 클라이언트가 제공하는 최종 콘텐츠가 서버가 예상한 것과 다를 때 클라이언트가 처음부터 다시 작성하라는 지시를 받는 것입니다. 이것은 애플리케이션 로직에 문제가 있다는 큰 표시입니다. 고맙게도 이 오류가 발생하기 시작하면 브라우저 콘솔(개발 모드에서)에 오류가 생성됩니다.
일반적인 문제인 세션 관리를 해결하는 방법의 예를 들어 보겠습니다. 계정에 로그인할 수 있는 Vue 앱이 있고 세션이 localStorage
에 유지하기로 결정한 토큰(예: JWT)을 사용하여 저장된다고 상상해 보십시오. 사이트에 처음 액세스할 때 유효한 경우 일부 기본 사용자 정보를 반환하고 해당 정보를 스토어에 저장하는 API에 대해 해당 토큰을 인증하려고 합니다.
Nuxt의 문서를 읽고 나면 초기 로드 시 Store를 비동기식으로 채울 수 있는 NuxtServerInit
라는 편리한 메서드가 있음을 알 수 있습니다. 완벽하게 들리네요! 따라서 Store에서 사용자 모듈을 만들고 Store 디렉터리의 index.js
파일에 적절한 작업을 추가합니다.
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 예제를 사용하겠습니다.
먼저 package.json
에서 Heroku용 스크립트를 설정합니다.
"scripts": { "dev": "nuxt", "build": "nuxt build", "start": "nuxt start", "heroku-postbuild": "npm run build" }
그런 다음 heroku-cli
를 사용하여 Heroku 환경을 설정합니다(설정 지침:
# 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 앱이 전 세계에 공개될 준비가 되었습니다. 다른 플랫폼에는 다른 설정이 있지만 프로세스는 비슷합니다. 현재 나열된 공식 배포 방법은 다음과 같습니다.
- 지금
- 도쿠(디지털 오션)
- 엔진엑스
단일 페이지 애플리케이션(SPA)
Nuxt가 제공하는 추가 기능 중 일부를 활용하고 싶지만 서버가 페이지를 렌더링하는 것을 피하고 싶다면 대신 SPA로 배포할 수 있습니다.
먼저, 기본적으로 npm run dev
는 SSR을 켠 상태에서 실행하므로 SSR 없이 애플리케이션을 테스트하는 것이 가장 좋습니다. 이를 변경하려면 nuxt.config.js
파일을 편집하고 다음 옵션을 추가하십시오.
mode: 'spa',
이제 npm run dev
를 실행하면 SSR이 꺼지고 애플리케이션이 테스트할 SPA로 실행됩니다. 또한 이 설정은 향후 빌드에 SSR이 포함되지 않도록 합니다.
모든 것이 괜찮아 보이면 배포는 SSR 앱의 경우와 정확히 동일합니다. 빌드 프로세스에서 SPA를 원한다는 것을 알리려면 먼저 mode: 'spa'
를 설정해야 한다는 것을 기억하십시오.
정적 페이지
서버를 전혀 다루지 않고 대신 Surge 또는 Netlify와 같은 정적 호스팅 서비스에 사용할 페이지를 생성하려는 경우 선택할 수 있는 옵션입니다. 서버가 없으면 컨텍스트의 req
및 res
에 액세스할 수 없으므로 코드가 이에 의존하는 경우 이를 수용해야 합니다. 예를 들어, 예제 프로젝트를 생성할 때 nuxtServerInit
함수는 요청 헤더의 쿠키에서 토큰을 가져오려고 하기 때문에 오류를 발생시킵니다. 이 프로젝트에서는 해당 데이터가 어디에도 사용되지 않기 때문에 문제가 되지 않지만 실제 애플리케이션에서는 해당 데이터에 액세스할 수 있는 대체 방법이 필요합니다.
일단 정렬되면 배포가 쉽습니다. 가장 먼저 변경해야 할 사항은 nuxt generate
명령이 대체 파일도 생성하도록 옵션을 추가하는 것입니다. 이 파일은 Nuxt가 호스팅 서비스가 아닌 라우팅을 처리하도록 호스팅 서비스에 프롬프트를 표시하여 404 오류를 발생시킵니다. 이렇게 하려면 nuxt.config.js
에 다음 줄을 추가합니다.
generate: { fallback: true },
다음은 현재 Nuxt 문서에 없는 Netlify를 사용하는 예입니다. 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 페이지
더 알아보기
Nuxt는 빠르게 업데이트되고 있으며 이는 Nuxt가 제공하는 기능 중 일부에 불과합니다. 이 기사를 통해 Vue 애플리케이션의 기능을 개선하고 더 빠르게 개발하고 강력한 기능을 활용할 수 있는지 확인하는 것이 좋습니다.
더 많은 정보를 찾고 있다면 Nuxt의 공식 링크를 참조하십시오.
- 선적 서류 비치
- 운동장
- 깃허브
- 자주하는 질문
JavaScript 게임을 찾고 계십니까? 동료 Toptaler Marko Mišura의 The Comprehensive Guide to JavaScript Design Patterns를 읽어보십시오.