Reactコンポーネントをnpmで公開するときにやること
React コンポーネントを webpack、babel等を使ってnpmとして公開するまでの手順。
環境準備
まずはプロジェクトディレクトリを作成して、必要なファイルを作成する(ドットファイルだったりREADMEだったり)。
$ mkdir react-hoge $ cd react-hoge $ touch README.md .editorconfig .babelrc .eslintrc webpack.config.babel.js
必要なファイルを作ったらpackage.jsonを作って必要なnpmモジュールをインストールする。
$ yarn init
$ yarn add babel-runtime prop-types
$ yarn add --dev autoprefixer ava babel-cli babel-core babel-eslint .... webpack webpack-dev-server
npmモジュールのインストールが完了したらwebpackの設定をする。
import webpack from 'webpack' import path from 'path' import HtmlWebpackPlguin from 'html-webpack-plugin' export default { entry: { app: [ './src/js/app.js', ], }, resolve: { extensions: ['', 'js', 'jsx'], }, output: { path: path.join(__dirname, 'dist'), filename: 'js/[name].js', publicPath: '/', }, resolve: { modules: [ 'node_modules', path.join(__dirname, 'src'), ], }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /(node_modules)/, include: [ path.resolve(__dirname, 'src/js'), ], use: [ { loader: 'babel-loader', options: { cacheDirectory: false, }, }, ], }, { test: /\.(js|jsx)$/, exclude: /(node_modules)/, include: [ path.resolve(__dirname, 'src/js'), ], use: [ { loader: 'eslint-loader', options: { }, }, ], }, { test: /\.scss$/, include: path.resolve(__dirname, 'src/scss'), use: [ { loader: 'style-loader', options: { singleton: true, }, }, { loader: 'css-loader', options: { minimize: true, }, }, { loader: 'postcss-loader', options: { plugins: (loader) => [ require('autoprefixer')(), ], }, }, { loader: 'sass-loader', }, ], }, ], }, devServer: { contentBase: './dist', publicPath: '/', port: 8080, }, plugins: [ new HtmlWebpackPlguin({ filename: 'index.html', inject: false, template: './src/templates/index.ejs', }), ], }
.babelrcの設定もする。
{ "presets": [ [ "env", { "targets": { "browsers": ["last 3 versions"], }, } ], "react" ], "plugins": [ "transform-object-assign", "transform-class-properties", "transform-runtime" ], "env": { "development": { "presets": ["react-hmre"], "plugins": [ [ "react-transform", { "transforms": [ { "transform": "react-transform-hmr", "imports": ["react"], "locals": ["module"] } ] } ] ] } } }
原因が良く分かってないけど、postcss.config.jsを用意しないとwebpackでエラーになるので、postcss.config.jsを用意する。
module.exports = {}
srcディレクトリにJSファイル、CSSファイル、ejsファイルを用意する。テスト用にのファイルも作る。
$ mkdir -p src/js/lib src/scss src/templates $ touch src/js/app.js $ touch src/js/lib/index.js $ touch src/scss/app.scss $ touch src/templates/index.ejs $ mkdir __test__ $ touch __test__/index.js
あとはpackage.jsonのscripts
を用意して環境の準備は完了。
"scripts": { "start": "NODE_ENV=development webpack-dev-server --inline --hot --color", "build": "NODE_ENV=production ./node_modules/.bin/babel ./src/js/lib --out-dir ./lib", "docs": "NODE_ENV=production webpack", "test": "NODE_ENV=test ava __test__/*.js --verbose", "prepublish": "yarn run build" },
デモ画面作成 + コンポーネント作成
コンポーネントを確認する用 + github pagesで公開する用のテンプレートを用意して、src/js/app.js
を読み込むようにする。
コンポーネントはsrc/js/app.js
でimport
する。
テンプレートになるsrc/templates/index.ejs
に適当なHTMLを用意してsrc/js/app.js
を読み込む。
<div id="js-app"></div> <script src="./js/app.js"></script>
src/js/app.js
の方でsrc/js/lib/
配下に用意するコンポーネントをimport
して使う。
import React from 'react' import ReactDOM from 'react-dom' import HogeComponent from './lib' import '../scss/app.scss' class App extends React.Component { render () { return ( <div> <HogeComponent /> </div> ) } } ReactDOM.render(<App />, document.getElementById('js-app'))
あとはコンポーネントを./lib/index.js
の方でコンポーネントを作る。
github pagesにデモページを公開
コンポーネントが出来上がったら、github pagesでデモを公開する。 デモページ用のファイルの生成は自動化したいので、travisからビルドしてcommitするようにする。
最初にgithubでアクセストークンを作っておく。 https://github.com/settings/tokens
作ったアクセストークンを暗号化するためのgemをインストールしておく。
$ sudo gem install travis
プロジェクトのルートディレクトリに.travis.yml
を作成する。
$ touch .travis.yml
先ほど入れたgem、travisでアクセストークンを暗号化する。
$ travis encrypt GH_TOKEN="アクセストークン" Please add the following to your .travis.yml file: secure: "..."
Please add the following to your .travis.yml file:
の下に表示されるsecure
以降を.travis.yml
に貼り付ける。
env: secure: "..."
travisからgh-pages
ブランチにデモページ用のファイルをコミットするように、shellscriptdocs.sh
を用意する。
#!/bin/sh rm -rf gh_pages || exit 0; mkdir gh_pages ls -la cd gh_pages cp -r ../dist/* . git init git config user.name "${GIT_COMITTER_NAME}" git config user.email "${GIT_COMITTER_EMAIL}" ls -la git add . git commit -m "Deploy to gh-pages" git push -fq "https://${GH_TOKEN}@github.com/${GH_REPO}.git" master:gh-pages > /dev/null 2>&1
内容としては、./dist
配下に生成済みのデモページ用ファイルをgh_pages
ディレクトリにコピーして、gh_pages
ディレクトリでgit init
して、gh_pages
ブランチにpushするもの。
最終的に用意する.travis.yml
は以下のような形。after_success
でscript
が通ったら、yarn run docs
でデモページ用ファイルを生成してgh_pages
ブランチにコミットするようになる。
language: node_js env: global: - GH_REPO="user/reponame" - GIT_COMMITTER_NAME=username - GIT_COMMITTER_EMAIL=user@example.com - GIT_AUTHOR_NAME=username - GIT_AUTHOR_EMAIL=user@example.com - secure: [暗号化されたtoken] node_js: - '6' - '7' - '8' script: yarn run test after_success: - npm rebuild node-sass - test ${TRAVIS_TAG} && yarn run build - yarn run docs && ./docs.sh cache: directories: - node_modules
npm publish
npm scriptsでnpmにpublishする直前にビルドするようにしておく。
"build": "NODE_ENV=production ./node_modules/.bin/babel ./src/js/lib --out-dir ./lib", "prepublish": "yarn run build"
package.json
のバージョンを任意のバージョンにしたら、gitでtagつけておく。
$ git tag x.x.x
$ git push origin master --tags
tagつけたものがCIで問題なければ、npmに公開する。
$ npm publish
これが全体的な流れ。 README、テスト、changelogなどについては省略してる。