9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

docker + webpack-dev-server で s2sのshopping-cartのサンプルを試してみたメモ

Posted at

s2sをdockerで試してみたメモのつづき。
s2sを動かしてみたメモ。

動作環境

  • windows10
  • vagrant1.9.7
  • virtualbox5.1.26
  • ubuntu-16.04
  • Docker version 17.09.0-ce, build afdb6d4
  • docker-compose version 1.17.1, build 6d101fb

ディレクトリ構成

- app
  - docker
    - s2s
      - Dockerfile
    - docker-compose.yml
  + src

エディタの環境設定

Flowは使ったことがなかったのでVSCodeの拡張を適用。
Flow Language Supportflow-vscode-ideをとりあえずいれてみた。

npm i -D flow flow-bin
package.json
{
  "devDependencies": {
    "flow": "^0.2.3",
    "flow-bin": "^0.59.0"
  }
}

.vscode/settings.json
{
  "files.associations": {
    "*.js": "javascriptreact"
  }
  ,"javascript.validate.enable": false
  ,"flow.useNPMPackagedFlow": true
  ,"flow.pathToFlow": "./node_modules/.bin/flow"
}

2017-11-18.png

この時点のソース

実践

さよならボイラーテンプレートのshopping-cartを試す。

起動

cd docker && docker-compose upでs2sを起動。

2017-11-19.png

actionTypes.jsの作成

まずは、actionTypes.jsを作成してみる。
空のファイルを作って名前をつけて保存する。
以下の文がs2sによって記述される。

src/App/actionTypes.js
// @flow

export const Actions = {};

export type Action = ;

2017-11-19 (1).png

no such file or directoryとかのエラーが出ているけれど、まだreducer.jsを作っていないので無視。

actionTypes.jsのActionにAddを追加

次に、export type Action = ;を完成させる。
export type Action = Add;まで書いて保存する。
以下のように補完される。

src/App/actionTypes.js
// @flow
export const ADD: 'App/ADD' = 'App/ADD'

export const Actions = {
  ADD,
}

export type Add = {
  type: typeof ADD,
}

export type Action = Add

さらにactions.jsを作成してくれる。

src/App/actions.js
// @flow
import { ADD } from './actionTypes'
import type { Add } from './actionTypes'

export function add(): Add {
  return {
    type: ADD,
  }
}

actionに変数nを追加

n: numberを以下のように追加して保存。

src/App/actionTypes.js
// @flow
export const ADD: 'App/ADD' = 'App/ADD'

export const Actions = {
  ADD,
}

export type Add = {
  type: typeof ADD,
  n: number,
}

export type Action = Add

actions.jsが更新される。

src/App/actions.js
// @flow
import { ADD } from './actionTypes'
import type { Add } from './actionTypes'

export function add(n: number): Add {
  return {
    type: ADD,
    n,
  }
}

reducerの作成

空のファイルreducer.jsを作成する。
以下の文がs2sによって記述される。

src/App/reducer.js
// @flow
import type { Action } from '../../types'
import { Actions } from './actionTypes'

export type State = {}

export const initialState: State = {}

export default function(
  state: State = initialState,
  action: Action
): Exact<State> {
  switch (action.type) {
    default:
      return state
  }
}

さらに、reducer.test.jsも作成される。

src/App/reducer.test.js
// @flow
import reducer, { initialState } from './reducer'
import * as actions from './actions'

test('provide the initial state', () => {
  expect(reducer(undefined, { type: '@@INIT' })).toEqual(initialState)
})

Actionの追加

reducer.jsがある状態で、actionTypes.jsを再度保存すると、reducer.jsにcaseが追加される。

src/App/reducer.js
// @flow
import type { Action } from '../../types'
import { Actions } from './actionTypes'

export type State = {}

export const initialState: State = {}

export default function(
  state: State = initialState,
  action: Action
): Exact<State> {
  switch (action.type) {
    case Actions.ADD:
      return {
        ...state,
      }

    default:
      return state
  }
}

reducer.test.jsも更新される。

src/App/reducer.test.js
// @flow
import reducer, { initialState } from './reducer'
import * as actions from './actions'

test('provide the initial state', () => {
  expect(reducer(undefined, { type: '@@INIT' })).toEqual(initialState)
})

test('handle ADD', () => {
  expect(reducer(initialState, actions.add())).toEqual({})
})

stateの追加

reducer.jsのexport type State = {}export type state={count:number}に変更する。
保存すると、initialStateが設定される。
export const initialState: State = { count: 0 }

reducerの完成(手作業)

自動化されているのはここまでっぽい。
Addのときに、nをcountに追加する部分を記述。

src/App/reducer.js
// @flow
import type { Action } from '../../types'
import { Actions } from './actionTypes'

export type State = { count: number }

export const initialState: State = { count: 0 }

export default function(
  state: State = initialState,
  action: Action
): Exact<State> {
  switch (action.type) {
    case Actions.ADD:
      return {
        ...state,
        count: state.count + action.n,
      }

    default:
      return state
  }
}

reducer.test.jsにactions.add()の引数と、toEqualの結果を記述。

reducer.test.js
// @flow
import reducer, { initialState } from './reducer'
import * as actions from './actions'

test('provide the initial state', () => {
  expect(reducer(undefined, { type: '@@INIT' })).toEqual(initialState)
})

test('handle ADD', () => {
  expect(reducer(initialState, actions.add(2))).toEqual({count: 2})
})

テスト確認

package.jsonにテストを動かすスクリプトが書かれていたので実行してみる。

cd docker && docker-compose run s2s npm run test

2017-11-19 (3).png

この時点のソース

s2sのサンプルを動かした環境

srcディレクトリ内にはgitからshopping-cartのsrcをコピー。

docker/docker-compose.yml
version: '3'
services:
  s2s:
    build: ./s2s
    volumes:
      - ../src:/app/s2s/examples/shopping-cart/src
      - ./config/.flowconfig:/app/s2s/example/shopping-cart/.flowconfig
      - ./config/s2s.config.js:/app/s2s/example/shopping-cart/s2s.config.js
    command: [yarn, run, s2s]
docker/s2s/Dockerfile
FROM node:9.2.0

# コンテナ上の作業ディレクトリ作成
WORKDIR /app

# ソースダウンロード
RUN git clone --depth=1 https://github.com/akameco/s2s.git

# chokidarのポーリング設定
RUN sed -i -e "s/\(ignoreInitial: true,\)/\1\n    usePolling: true, /g" /app/s2s/packages/s2s-cli/src/index.js

# s2sをビルド
WORKDIR /app/s2s/
RUN yarn

# example用設定
WORKDIR /app/s2s/examples/shopping-cart
RUN yarn
RUN yarn run flow
docker/config/s2s.config.js
// @flow
const plugins = require('s2s-plugins-redux')

module.exports = {
  watch: './**/*.js',
  plugins,
  templates: [
    { test: /containers\/.*\/index.js/, input: 'containers.js' },
    { test: /components\/.*\/index.js/, input: 'components.js' },
    { test: /components\/.*\/index.test.js/, input: 'component.test.js' },
    { test: /reducer.js/, input: 'reducer.js' },
    { test: /reducer.js/, input: 'reducer.test.js', output: 'reducer.test.js' },
    { test: /reducer.js/, input: 'actionTypes.js', output: 'actionTypes.js' },
    { test: /selectors.js/, input: 'selectors.js' },
    { test: /selectors.test.js/, input: 'selectors.test.js' },
    { test: /logic.js/, input: 'logic.js' },
  ],
}
docker/config/.flow
[ignore]
.*/templates/.*

[include]

[libs]

[lints]

[options]

ブラウザで実行確認

cd docker && docker-compose up

そのまま動かそうとしたら以下のエラー。

Uncaught TypeError: Cannot read property 'apply' of undefined
    at compose.js:29
    at createStore (createStore.js:51)
    at exports.default (store.js:10)
    at Object.<anonymous> (index.js:10)
    at __webpack_require__ (bootstrap 7bc4a4fa37f65eb57f87:19)
    at Object.<anonymous> (bundle.js:2296)
    at __webpack_require__ (bootstrap 7bc4a4fa37f65eb57f87:19)
    at module.exports (bootstrap 7bc4a4fa37f65eb57f87:62)
    at bootstrap 7bc4a4fa37f65eb57f87:62

store.jsの window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()でエラーが出ていた。

redux-devtools-extension にしたがいRedux DevToolsをchromeに追加。
動いた。
2017-11-20.png

この時点のソース

動作確認環境

ディレクトリ構成

- app
  - docker
    - config
      - .babelrc
      - .flowconfig
      - s2s.config.js
      - webpack.config.js
    - s2s
      - Dockerfile
    - webpack
      - Dockerfile
    - docker-compose.yml
  + src
  + public

ブラウザで確認した環境

publicディレクトリ内にはgitからshopping-cartのpublicをコピー。

ブラウザで確認するためにwebpack-dev-serverを使用する。

docker/docker-compose.yml
version: '3'
services:
  s2s:
    build: ./s2s
    volumes:
      - ../src:/app/s2s/examples/shopping-cart/src
      - ./config/.flowconfig:/app/s2s/example/shopping-cart/.flowconfig
      - ./config/s2s.config.js:/app/s2s/example/shopping-cart/s2s.config.js
    command: [yarn, run, s2s]

  webpack:
    build: ./webpack
    volumes:
      - ../src:/app/src
      - ./config/.flowconfig:/app/.flowconfig
      - ./config/.babelrc:/app/.babelrc
      - ./config/webpack.config.js:/app/webpack.config.js
      - ../public:/app/public
      - ../dist:/app/dist
    ports:
      -  8080:8080
    command: [npm, run, dev-server, --, --history-api-fallback]
docker/webpack/Dockerfile
FROM node:9.2.0

# コンテナ上の作業ディレクトリ作成
WORKDIR /app

# package.jsonを作成
RUN npm init -y

# ビルドツール
RUN npm i -D webpack

# 開発用サーバ
RUN npm i -D webpack-dev-server

# es6用トランスパイラ
RUN npm i -D babel-loader
RUN npm i -D babel-preset-es2015
RUN npm i -D babel-preset-react
RUN npm i -D babel-preset-stage-2

# flow
RUN npm i -D flow
RUN npm i -D flow-bin
RUN npm i -D babel-plugin-transform-flow-strip-types

# jsViewライブラリreact
RUN npm i -S react
RUN npm i -S react-dom
RUN npm i -S react-redux
RUN npm i -S react-scripts

# フレームワーク
RUN npm i -S redux
RUN npm i -S redux-thunk

RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"flow\": \"flow\",/g" /app/package.json
RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"babel\": \"babel\",/g" /app/package.json
RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"webpack\": \"webpack\",/g" /app/package.json
RUN sed -i -e "s/\(\"scripts\": {\)/\1\n    \"dev-server\": \"webpack-dev-server\", /g" /app/package.json
docker/config/.babelrc
{
  "presets": [
    "react",
    "es2015",
    "stage-2"
  ],
  "plugins": [
    "transform-flow-strip-types"
  ]
}
docker/config/.flowconfig
[ignore]
.*/templates/.*
.*/node_modules/.*

[include]

[libs]

[lints]

[options]
docker/config/webpack.js
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: '/app/dist'
  },
  devtool: "source-map",
  resolve: {
    extensions: [".jsx", ".js"]
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      }
    ]
  },
  performance: {
    hints:false
  },
  devServer: {
    // public/index.htmlをデフォルトのホームとする
    contentBase: './public',
    // インラインモード
    inline: true,
    // 8080番ポートで起動
    port: 8080,
    // dockerのコンテナ上でサーバを動かすときは以下の設定で全ての接続を受け入れる
    host:"0.0.0.0",
  },
  // vagrantの仕様でポーリングしないとファイルの変更を感知できない
  watchOptions: {
    aggregateTimeout: 300,
    // 5秒毎にポーリング
    poll: 5000
  }
};

参考

type can be used by only '.ts' files
Visual Studio CodeでFlowTypeのエラーを表示する
さよならボイラープレート。s2sによる高速reduxアプリケーション構築
Flowを使ってアプリケーション開発するためのエディタ環境いろいろ
Flow導入時に最初にやることまとめ
React + flow + Webpackの最小構成
webpack history api fallback

9
6
0

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
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?