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などについては省略してる。