#nuxt

Installation

1
2
3
4
5
6
7
8
vue init nuxt-community/typescript-template [프로젝트 명];

yarn add nuxt-property-decorator && # property decorator installation
yarn add tsconfig-paths-webpack-plugin &&# webpack 에서 typescript 를 사용하기 위한 세팅
yarn add ts-loader && # typescript 사용을 위한 ts-loader 설치
yarn add vuex-class && # Vuex 를 class 타입으로 사용하기 위해 설치
yarn add nuxt-sass-resources-loader && # For using sass
yarn add sass-loader # for using sass

타입스크립트를 트랜스파일링 하기 위해 webpack configuration을 바꾸어 주어야 한다.

이는 nuxt.config.js 에서 webpack configuration 을 overriding 함으로써 구현한다.

nuxt.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
config.resolve.extensions.push('.ts');

const tsLoader = {
loader: 'ts-loader',
options: { appendTsSuffixTo: [/\.vue$/], transpileOnly: true },
exclude: [/vendor/, /\.nuxt/]
};

config.module.rules.push({ test: /.tsx?$/, ...tsLoader });

for (let rule of config.module.rules) {
if (rule.loader === 'vue-loader') {
rule.options.loaders = {
ts: tsLoader
};
}
}

let plugin = new TsconfigPathsPlugin({
configFile: 'tsconfig.json' // setup tsconfig path
});

config.resolve['plugins'] = [plugin];
}
}

Next CLI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# install dependencies

$ npm install # Or yarn install

# serve with hot reload at localhost:3000

$ npm run dev

# build for production and launch server

$ npm run build

$ npm start

# generate static project

$ npm run generate

Vuex

store 디렉토리는 어플리케이션에서 사용하는 도메인 객체들의 저장소이다.

초기 프로젝트는 Vuex 가 disable 된 상태이나 다음과 같이 store/index.js 파일을 작성하면, Vuex 를 사용할 수 있다.

store/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vuex from 'vuex';

const createStore = () => {
return new Vuex.Store({
state: () => ({
counter: 0
}),
mutations: {
increment(state) {
state.counter++;
}
}
});
};

export default createStore;

Vuex state 의 경우 nested 된 object 의 경우 내부 값만 바뀌면 store 가 업데이트 되지 않는 현상이 있다.

이를 위한 해결법으로 state.prop[key] ={} 와 같은 연산이 있다면 이를 state.prop={[key]:{}} 와 같이 수정하는 트릭을 쓸 수 있다.

Global CSS

nuxt.config.js 에서 head 에 추가한다.

Setup Vuetify

1
yarn add @nuxtjs/vuetify
1
2
3
4
import Vuetify from 'vuetify';

Vue.use(Vuetify);
import 'vuetify/dist/vuetify.min.css'; // Ensure you are using css-loader

nuxt.config.js

1
2
3
4
5
6
7
8
9
10
{
modules: [
'@nuxtjs/vuetify'
],

// Vuetify options
vuetify: {
// theme: { }
}
}

Nuxt 에서 axios 사용하기

기본 사용법

Nuxt 에서는 기본적으로 다음과 같은 방법을 통해 axios 모듈을 사용할 수 있다.

여기서, 왜 그냥 axios 를 동적으로 import 해서 사용하지 않고 nuxt 가 제공하는 axios 를 사용해야 하는지 궁금할 수 있다.

바로 그 이유는, nuxt 는 기본적으로 server redering 방식으로 동작하기 때문에, browser cookie 와 jwt 토큰 등의 중앙적인 데이터에 접근하기가 힘들기 때문이다.

nuxt 가 제공하는 axios 는 withCredential 등을 통해 간편하게 cookie 데이터에 접근할 수 있는 장점이 있다.

axios 설치

1
npm install @nuxtjs/axios

axios 모듈 등록

nuxt.config.ts

1
2
3
4
5
6
7
8
module.exports = {
modules: [
'@nuxtjs/axios',
],
axios: {
// proxyHeaders: false
}
}

이를 통해 각 component 의 this.$axioscontext 의 $axios 를 통해 axios를 사용할 수 있다.

하지만, 여기서는 범용 logger 혹은 http request 에 있어서 일관된 에러 핸들링 등을 할 수 없기 때문에 이 함수를 사용하는 httpHelper 플러그인을 구현하여 이를 가능하도록 한다.

http helper plugin 적용

여기서 httpHelper의 경우 get, post, put, delete 등의 메소드를 wrapping 하는 다양한 함수들이 존재하며 여기서는 구현을 생략하겠다.

중요한 점은 이런 HttpHelper 클래스가 plugin 에서 $axios 를 주입받아 새로운 메소드를 구현하며, 이를 inject 함수를 통해 vue instance, store, context 에 바인딩 하여 어느 곳에서나 사용 가능하게 해준다는 것이다.

plugins/httpHelper.ts

1
2
3
4
5
6
7
8
9
import { HttpHelper } from 'utils/httpHelper';

export default function(context, inject) {
let { $axios } = context;
let httpHelper = new HttpHelper($axios);
context.$httpHelper = httpHelper;

inject('httpHelper', httpHelper);
}

Plugin 사용하기

Vue.js 의 자체 기능 뿐 아니라 다양한 외부 라이브러리 혹은 사용자의 external util function 등을 활용하기 위해서 nuxt 는 plugin 이라는 기능을 제공한다.

이러한 plugin 을 통해서 사용자는 사용하고자 하는 함수 혹은 instance 를 vue root application 혹은 context 에 binding 할 수 있다.

플러그인 만들기

plugins/sample.ts

1
2
3
4
5
export default (context, inject) => {
context.$sample = a => {
console.log(a);
};
};

플러그인 등록하기

플러그인을 사용하기 위해 nuxt configuration 에 등록시켜 주어야 한다.
nuxt.config.ts

1
2
3
export default {
plugins: ['~/plugins/sample.ts']
};

Vue instance, Contextk, Store 에서 사용가능하게 등록하기

기본적으로 plugin 을 등록하면 오직 context 혹은 vue instance 내에서만 사용 가능하다.
하지만 store 혹은 여러 곳에서 이 함수 혹은 인스턴스에 접근하고자 한다면 inject 함수를 이용하여 전역에서 사용가능하게 등록시켜 주어야 한다.

아래처럼 'sample' 과 같이 $ 기호를 생략하고 등록해 주면 $sample 과 같이 변형되어 바인딩 된다.

1
2
3
4
5
6
7
8
9
10
11
12
export default (context, inject) => {
let sample = a => {
console.log(a);
};
let sample2 = {
b: x => {
console.log(x);
}
};
inject('sample', sample);
inject('sample2', sample2);
};

이를 통해 context, Vue 인스턴스 내에서의 this 등 어디에서는 이곳에 접근할 수 있게 된다.

Reverse proxy

클라이언트가 서버를 호출하는 경우 cors(cross origin resource sharing 문제로 브라우저 내에 렌더링 된 페이지를 준 호스트가 아닌 다른 곳으로의 요청은 기본적으로 막혀있다.

사실 이는 nuxt.js 뿐만이 아니라 대부분의 웹 어플리케이션 배포 과정에서 나타나는 문제인데, nuxt.js 에서는 그 해결과정이 조금 다르기 때문에 작성한다.

다른 어플리케이션 배포과정의 경우 일반적으로 nginx 와 같은 web server 를 사용하여 reverse proxy 를 통해 클라이언트 내의 서버 요청 url 을 같은 호스트로 설정하고, 같은 호스트로 오는 요청의 url 을 분석하여 같은 호스트 내의 다른 포트로 리다이렉팅 시켜주는 등의 해결법을 제시하지만, nuxt.js 의 경우 server rendering 프레임워크로 독자적으로 hosing 을 하는 만큼, 자체적으로 reverse proxy 를 제공하며, nuxt.config.js 파일에 다음과 같이 reverse proxy 설정을 주어 해결할 수 있다.

nuxt.config.js

1
2
3
4
5
6
7
const serverUrl = "localhost:3002";

module.exports = {
proxy: {
'/api/': serverUrl
},
}

Global Modal

전역으로 alert와 dialog를 사용하기 위해 layout 레이어에서 해당 모듈을 구현하였으며, 이는 page store 를 통해 접근이 가능하다.

Environment variables

node.js 서버와는 달리 nuxt 의 경우는 동작환경이 브라우저 이므로, 서버에서 하듯이 process.env 와 같이 환경변수에 접근해도 브라우저의 환경변수이기 때문에 접근이 되지 않는다. 이는 매우 기본적인 사실이지만 서버렌더링을 하는 과정에서 혼동될 수 있다.

즉, nuxt.js 에서 process.env 를 사용한다면, 이는 빌드시점에 주입되어야 할 것이다.

Problem solving

layout 사용하기

vue component class 를 사용함에 있어 layout 옵션이 설정되지 않았다면 다음 코드를 index.d.ts 에 추가한다.

1
2
3
4
5
6
7
8
9
declare module 'vue/types/options' {

interface ComponentOptions<V extends Vue> {

layout?: string;

}

}

Unexpected token import

모든 기능이 정산인데 갑자기 Unexpected token import 에러가 났다.

이 경우 최종 문제의 원인은

nuxt.config.js에서 modules 에 bootstrap-vue 를 import 함에 있어 bootstrap-vue/nuxt 가 아니라 @nuxtjs/bootstrap-vue 를 import 하여 생기는 문제였다.

bootstrap-vue 공식 홈페이지에도 bootstrap-vue/nuxt 를 import 하라고 하고 있는데, 이를 매우 주의하여야 한다.

cannot find module

nuxt property decorator 를 사용할때

1
{components:{}} 속성을 추가하지 않으면 모듈을 찾지 못하는 문제가 생긴다.

Query string nested object

기존에는 querystring 라이브러리를 사용하여 nested object 를 처리하지 못하였으나, qs 라이브러리를 사용하면 해결 가능하다.

Custom Component 의 click 이벤트를 자식 요소로 넘기는 법

1
@click.native

다른 vuex 모듈에서 다른 vuex 모듈에 있는 액션을 호출하는 법

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×