TypeScriptを使用したNext.js 5からNext.js 6へ移行した時行った対応について
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Next.jsはこのサイトでも使っているのですが
比較的容易にBFF(バックエンドフォーフロントエンド)が実現できるツールとして大変有用です。
UXを実現していくためにSPA(シングルーページアプリケーション)という
アーキテクトがあげられますが
単純なSPAとしての問題点であげられるのが
- リクエストの複雑化によるランドトリップ
- 初回ロード時間の遅延
このあたりの課題の解決としてBFFというアーキテクチャの設計思想があります。
そのためこれらの解決を実現していくために
このサイトではNext.js
を採用しました。
そんなNext.js6が5月にリリースされたため
マイグレーションのログとして内容をまとめました。
環境
- React 16.3.2
- Next.js 5.1
- typescript 2.8.3
terminal$ yarn upgrade --latest next next-redux-wrapper typescript
terminal$ yarn upgrade --latest @zeit/next-typescript @types/next
packageのバージョン
- next@5.1 → next@6.1.1
- next-redux-wrapper@1.3.7 → next-redux-wrapper@2.0.0-beta.6
- typescript@2.8.3 → typescript@2.9.2
- @zeit/next-typescript@0.1.1 → @zeit/next-typescript@1.1.0
- @types/next@2.4.8 → @types/next@6.0.3
next-redux-wrapper関連
アップデート後に出たエラー
terminal__WEBPACK_IMPORTED_MODULE_2_next_redux_wrapper__ is not a function
解決方法
書き方が変わりました。
next-redux-wrapper1系
getInitialPropsを呼び出したReact
クラスをwithRedux
でラップすることで
ステートを子コンポーネントで参照できます。
./pages/index.tsx
typescriptimport * as React from 'React';
import { createStore } from 'redux';
import * as withRedux from 'next-redux-wrapper';
import Page from './components/page';
const reducer = (state = {hoge: ''}, action) => {
switch (action.type) {
case 'HOGE':
return {...state, hoge: action.payload};
default:
return state
}
};
const makeStore = (initialState, options) => {
return createStore(reducer, initialState);
};
class App extends React.Component<object> {
public static getInitialProps({ store }: Context): void{
const state = store.getState();
await store.dispatch({type: 'Hoge', payload: 'hoge'});
}
public render(): JSX.Element {
return (
<Page />
);
}
}
export default withRedux(makeStore)(App);
受け取った props
を出力
./components/page.tsx
import * as React from 'React';
const Page = (props) => {
return <div>Prop from Redux {props.hoge}</div>
}
export default connect()(Page);
next-redux-wrapper2系
getInitialPropsを呼び出しreact-redux
に渡しProviderします
。
そのReact
クラスをwithRedux
でラップすることで
ステートを子コンポーネントで参照できます。
./pages/_app.tsximport * as React from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App, { Container } from 'next/app';
import withRedux from 'next-redux-wrapper';
const reducer = (state = { foo: '' }, action) => {
switch (action.type) {
case 'FOO':
return { ...state, foo: action.payload };
default:
return state
}
};
const makeStore = (initialState, options) => {
return createStore(reducer, initialState);
};
class MyApp extends App<object> {
static getInitialProps({ Component, ctx }) {
const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};
return { pageProps };
}
render() {
const { Component, pageProps, store } = this.props;
return (
<Container>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</Container>
);
}
}
export default withRedux(makeStore)(MyApp);
単純に withRedux
の箇所を _app.tsx
に切り出す形になりましたが
pagesがかなりシンプルになりました
各ページごとにストアへ保存するデータを分けてかくケースについては
以前よりかなりスッキリ見やすくなっています。
./components/page.tsximport * as React from 'React';
import Page from './components/page';
class MyApp extends React.Component<object> {
public static getInitialProps({ store }: Context):void{
const state = store.getState();
store.dispatch({type: 'Hoge', payload: 'hoge'});
}
public render(): JSX.Element {
return (
<Page />
);
}
}
export default App;
コネクト関数については以前と同じ形で使用できます。
./pages/index.tsximport * as React from 'React';
const Page = (props: object) => {
return <div>Prop from Redux {props.hoge}</div>
}
export default connect()(Page);
@zeit/next-typescript関連
アップデート後に出たエラー
typescriptLoaderOptionsはサポートされなくなりました
terminalError: `typescriptLoaderOptions` in next.config.js is no longer supported. https://err.sh/next-plugins/typescript-loader-options
解決方法
以下を削除
next.config.js typescriptLoaderOptions: {
transpileOnly: false
}
'next / babel'モジュールを見つけることができません
terminalUnhandledPromiseRejectionWarning: Error: Cannot find module 'next/babel' from '/Users/XXXX/XXXX'
解決方法
.babelrcを作成し下記を記述
.babelrc{
"presets": [
"next/babel",
"@zeit/next-typescript/babel"
]
}
記事Article
もっと見る- article
Dockerの利用していないゴミを掃除しディスクスペースを解放するいくつかのやり方を紹介
- article
Next.js のバンドルサイズを可視化する@next/bundle-analyzer の紹介
- article
VSCodeでTypescriptファイルのimport補完で相対パスではなくエイリアスするための設定
- article
UUIDより短いユニークなIDを生成できるnpmライブラリnanoidの使い方
- article
【解決方法】TypeScript発生したTS2564 エラーの対処
- article
express で IP を取得する際などに利用する req.connection 非推奨(deprecated)の対処