/nextjs-boilerplate

next.js boilerplate use css-in-js, i18n, jwt ...

Primary LanguageJavaScript

Next.js boilerplate

Features

How to use

Download the example or clone the repo:

git clone the repo

Install it and run:

yarn or 部屬只安裝生產依賴(yarn install --production)
yarn dev 

部屬環境

將 docker-compose.yml.sample 複製為 docker-compose.yml 根據需求更改 APP_ENV 來決定環境別(正式 production, 測試 sandbox, 開發 develop)

  • 啟動 (加上 -d 可常駐背景執行)
$ docker-compose up
  • 關閉
$ docker-compose down
  • 查詢已啟動狀態
$ docker-compose logs -f
  • 測試程式碼
$ yarn test
  • 執行ESLINT檢查
$ yarn lint

or 自動修復
$ yarn lint --fix
  • 啟動 storybook
$ yarn storybook

App Structure

.
├── __test__                                    # Jest測試程式位置
│   └── __snapshots__                           # Jest測試快照
├── .storybook                                  # storybook (元件開發與檢測)
├── pages                                       # 頁面 (選擇使用那個樣版,並在裡面規劃組織+組織)
├── src                                         # App source code
│   ├── components                              # 組件庫
│   │   ├── atoms                               # 元子 (最小的元件)
│   │   ├── molecules                           # 分子 (元子 + 元子)
│   │   ├── organisms                           # 組織 (分子 + 分子 or + 分子)
│   │   └── templates                           # 樣版
│   ├── styles                                  # SCSS樣式檔位置
│   ├── utils                                   # 工具方法
│   ├── server.js                               # Node 服務設定
│   └── i18next                                 # 多國語系的使用方法
├── static                                      # 靜態資源路徑
│   ├── css                                     # 樣式
│   ├── img                                     # 圖片
│   ├── plugin                                  # 套件
│   ├── locales                                 # 多國語系設定檔案
│   │   └── en                                  # 英文
│   │       └── common.json                     # 通用字典檔
│   ├── favicon.ico                             # 網站圖標
│   └── robots.txt                              # Google SEO忽略設定檔
├── .babelrc                                    # Babel設定檔
├── .env.sandbox                                # Sandbox站環境設定範本
├── .eslintignore                               # Eslint忽略設定檔
├── .eslintrc                                   # Eslint規則設定檔
├── .gitignore                                  # Git版控忽濾項目設定檔
├── jest.config.js                              # Jest測試設定檔
├── jest.setup.js                               # Jest額外設定檔
├── .next.config.js                             # Next設定&Webpack設定檔
├── package.json                                # 依賴套件設定
├── postcss.config.js                           # CSS預處理設定
├── webpack.config.js                           # Webpack-Webstorm路徑別名設定
├── .gitlab-ci.yml                              # Gitlab-CI 持續整合測試設定檔
└── docker-compose.yml.sample                   # Docker Compose 部屬設定檔

路徑設定

next.js pages path

in next.config.js

const app = next({ dir: './',dev })

import alias

可以省去相對路徑 ../../ 的麻煩

in .babelrc

alias name real path
@atoms src/components/atoms
@layouts src/components/templates
@molecules src/components/molecules
@organisms src/components/organisms
@i18next src/i18next
@styles src/styles
@utils src/utils

PS: webpack.config.js by webstorm alias

root-static-files

把指定檔案放在網址根目錄 (SSL驗證 或 Google Analytics驗證 會需要放置檔案在根目錄下)

參考 https://github.com/zeit/next.js/tree/master/examples/root-static-files

in server.js

// use next.js
server.get('*', (req, res) => {

    const parsedUrl = parse(req.url, true)
    const rootStaticFiles = [
        '/robots.txt',
        '/sitemap.xml',
        '/favicon.ico'
    ]
    if (rootStaticFiles.indexOf(parsedUrl.pathname) > -1) {
        app.serveStatic(req, res, path.join(__dirname, 'static', parsedUrl.pathname))
    } else {
        return handle(req, res)
    }

})

i18n多國語系設定

  • words add in static/locales/{語系}/字典檔
  • debug mode 開啟設定至 .env 新增 I18N_DEBUG=true (default:false)
  • 開發模式會將頁面上使用到的語系但字典檔未建立時, 會自動加入到 static/locales/{語系}/*.missing.json
  • How to change language in code:
import { translate } from 'react-i18next'
import i18n from '@i18n'


function Home ({ t,i18n }) {
    return (
        <Page>
            <div>
                {t('welcome')}
            </div>
        </Page>
    )
}

const Extended = translate(['common'], { i18n, wait: process.browser })(Home)

// Passing down initial translations
// use req.i18n instance on serverside to avoid overlapping requests set the language wrong
Extended.getInitialProps = async ({ req }) => {
    if (req && !process.browser) return i18n.getInitialProps(req, ['common'])
    return {}
}

export default Extended
  • How to change language in query string
get http://localhost?lang=zh-cn
  load: 
    'all' --> ['en-US', 'en', 'dev'], 
    'currentOnly' --> 'en-US', 
    'languageOnly' --> 'en'

可參考 localhost:3000/examples/i18next

CSS Styles Mode

  • Scss 設定全域的項目, 例如 Bootstrap 設定
  • 選擇使用 CSS-Modules 或 Styled-components 設計元件 (可選)

CSS Module BEM

使用skeleton-loader,之後會產生scss.json,再用trash刪除產生的json

BEN格式 [path][name]__[local]--[hash:base64:5]

.title{
  color: red;
}
import Head from 'next/head';
import {stylesheet, styles} from './index.scss'

return (
    <div>
        <Head>
            <style dangerouslySetInnerHTML={{__html: stylesheet}} />
        </Head>
        <p className={styles.title}>MY TITLE</p>
    </div>
)
    

可參考 localhost:3000/examples/css-modules

Package List

  • glob
  • prop-types
  • husky

處理JS物件套件

  • immutable

JS函示庫

  • jquery

程式碼品質檢測套件

  • eslint - 程式碼品質工具
  • eslint-config-airbnb - 程式碼品質工具
  • eslint-config-airbnb-base - 程式碼品質工具
  • eslint-plugin-import - 程式碼品質工具
  • eslint-plugin-jest - 程式碼品質工具
  • eslint-plugin-jsx-a11y
  • eslint-plugin-react

CSS轉譯套件

  • raw-loader
  • sass-loader
  • postcss-easy-import
  • postcss-loader
  • node-sass
  • styled-component
  • classnames (className標籤轉換)

CSS-MODULE 加裝

  • postcss-cssnext
  • postcss-modules
  • skeleton-loader

多國語系套件

  • react-i18next
  • i18next
  • i18next-browser-languagedetector
  • i18next-express-middleware
  • i18next-node-fs-backend
  • i18next-xhr-backend

網頁進度讀取條

  • nprogress

BABEL轉譯套件

  • babel-plugin-module-resolver
  • babel-plugin-styled-components
  • babel-polyfill
  • babel-preset-es2015
  • babel-preset-es2017
  • babel-preset-stage-0
  • babel-register

Cookie套件

  • js-cookie
  • cookie-parser

環境參數引入.env套件

  • dotenv
  • dotenv-webpack

後端服務套件

  • express

讓前後端可共用程式碼的套件

  • isomorphic-fetch

上線前壓縮用

  • cssnano

刪除檔案使用

  • trash

Jest測試工具

  • jest
  • eslint-plugin-jest
  • enzyme
  • enzyme-adapter-react-16
  • react-addons-test-utils
  • react-test-renderer

JWT使用工具

  • jsonwebtoken
  • jwt-decode

ESLINT 特別規範

  • 4格縮進, 搭配Webstorm預設的格式化(Shift+Command+L)設定,在 git commit 時也會自動格式化

Other Reference

Remarks

  • next.config.js的webpack設定路徑產生找不到css loader modules問題,故將 next pages 路徑移動回根目錄,避免導入Package異常 若更改專案根路徑, 需要修改 src/server.js 的i18next static路徑,
  • 在 babelrc 加上 env設定會產生 styled-components 的問題
"env": {
    "development": {
      "presets": "next/babel"
    },
    "production": {
      "presets": "next/babel"
    },
    "test": {
      "presets": [
        ["env", { "modules": "commonjs" }],
        "next/babel"
      ]
    }
  }
  • yarn build 出現警告

Warning: postcss-cssnext found a duplicate plugin ('autoprefixer') in your postcss plugins. This might be inefficient. You should remove 'autoprefixer' from your postcss plugin list since it's already included by postcss-cssnext.

因為 cssnext 跟 cssnano 都包含了 autoprefixer, 所以會出現此警告, 可無視
參考 http://cssnext.io/usage/#features
  • jest test 針對 styled-component 的內容無法比對