LoginSignup
78
52

More than 3 years have passed since last update.

最近っぽいnext.jsの設定

Last updated at Posted at 2018-08-26

この記事について

next.jsを友人と趣味の開発で使用することになったので
しばらく使っていなかった分調べ直して環境構築したメモ

使っているアーキテクチャ

  • react
  • next
  • redux
  • typescript
  • styled-jsx

ディレクトリ

pages(nextのお作法)
src(componentとか入れる用)
types(typescriptの定義ファイルいれる)
.babelrc
next.config.js
package.json
tsconfig.json

設定

package.json
{
  "name": "next-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@types/next": "^6.1.2",
    "@types/next-redux-wrapper": "^2.0.0",
    "@types/react": "^16.4.11",
    "@types/react-redux": "^6.0.6",
    "@zeit/next-typescript": "^1.1.0",
    "module-alias": "^2.1.0",
    "next": "^6.1.1",
    "next-redux-wrapper": "^2.0.0",
    "react": "^16.4.2",
    "react-dom": "^16.4.2",
    "react-redux": "^5.0.7",
    "redux": "^4.0.0"
  },
  "devDependencies": {
    "@types/node": "^10.9.1",
    "babel-plugin-module-resolver": "^3.1.1",
    "fork-ts-checker-webpack-plugin": "^0.4.9",
    "redux-devtools-extension": "^2.13.5",
    "typescript": "^3.0.1"
  },
  "_moduleAliases": {
    "~": "src"
  }
}

ポイント
- _moduleAliases をつけないと~をaliasに設定した時typecheckで弾かれる

tsconfig.json
{
  "compileOnSave": false,
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "jsx": "preserve",
    "allowJs": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "removeComments": false,
    "preserveConstEnums": true,
    "sourceMap": true,
    "skipLibCheck": true,
    "baseUrl": "./",
    "paths": {
      "~/*": ["src/*"]
    },
    "noImplicitThis": true,
    "lib": [
      "dom",
      "es2016"
    ],
    "typeRoots":[
      "node_modules/@types",
      "./types"
    ],
    "rootDirs": ["./pages", "./src"]
  }
}
{
  "presets": [
    "next/babel",
    "@zeit/next-typescript/babel"
  ],
  "plugins": [
    [
      "module-resolver", {
        "alias": {
          "~": "./src"
        }
      }
    ]
  ]
}
next.config.js
const withTypescript = require('@zeit/next-typescript')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
const path = require('path')

module.exports = withTypescript({
  webpack(config, options) {
    config.resolve.alias = {
      ...config.resolve.alias,
      '~': './src'
    }

    // typecheckする
    if (options.isServer) {
      config.plugins.push(new ForkTsCheckerWebpackPlugin())
    }

    return config
  }
})

tsxファイル

_app.tsx
import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App, { Container } from 'next/app'
import withRedux from 'next-redux-wrapper'
import { devToolsEnhancer } from 'redux-devtools-extension'

const reducer = (state = {foo: ''}, action) => {
  switch (action.type) {
    case 'FOO':
      return {...state, foo: action.payload};
    default:
      return state
  }
};

const makeStore = (initialState, _) => {
  return createStore(
    reducer,
    initialState,
    devToolsEnhancer({})
  )
}

interface AppProps {
  Component: React.Component
  pageProps: any
  store: any
}

class MyApp extends App<AppProps> {
  static async getInitialProps({ Component, ctx }) {
    ctx.store.dispatch({type: 'FOO', payload: 'foo'})

    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)
  • storeはsrc/storeにディレクトリを作ってやっていく予定
  • reduxは使い込んでいないのでいまいちわかっていない。オススメの記事あったら教えてください。
pages/index.tsx
import React, { Component } from 'react'
import { connect } from 'react-redux'

// Components
import DefaultLayout from '~/components/layouts/default'

interface PageProps {
  foo: string
  custom: string
}

class Page extends Component<PageProps> {
  static getInitialProps({ store }) {
    store.dispatch({type: 'FOO', payload: 'foo'})

    return { custom: 'custom', ...store.getState() }
  }

  render() { 
    return (
      <DefaultLayout>
        <p>Props from Redux { this.props.foo }</p>
        <p>Props from getInitialProps { this.props.custom }</p>
        <p>welcome to next.js!</p>
        <style jsx>
        {`
          p {
            color: red;
          }
        `}
        </style>
      </DefaultLayout>
    )
  }
}

export default connect()(Page)
src/components/layouts/default/index.tsx
interface DefaultLayoutProps {
  children: React.ReactNode
}

const DefaultLayout: React.SFC<DefaultLayoutProps> = (props: DefaultLayoutProps) => {
  return (
    <div>
      <header>header</header>
      { props.children }
      <footer>footer</footer>
    </div>
  )
}

export default DefaultLayout
  • components内はできるだけSFCで書けるように
  • export constだとreact dev toolでcomponent名がunknownになっちゃう・・・
types/styled-jsx.d.ts
import 'react'

declare module 'react' {
  interface StyleHTMLAttributes<T> extends React.HTMLAttributes<T> {
    jsx?: boolean
    global?: boolean
  }
}
  • styled-jsx使うための定義ファイル

最後に

  • 環境構築自体は使うものを決めてしまえばやはり使いやすい
  • 暫定でやっているところが多いので(特にstore周り)作り込んでいったらテンプレートとしてgithubにおいておきたい
  • typescriptは最近使い始めてあんまりわかっていないと思うので、今の時点で何かあれば教えてください

next.jsは1年近く使っていましたが、最近使っていなかったです。
気づいたら_app.jsとかもできてた・・・containerって名前、前のプロジェクトとかでも使っていたけど
もうnextで使われているから気をつけないとと思いました。

78
52
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
78
52