オリジナルのコンポーネントライブラリを作って公開するまでの手順です。
著者も試行錯誤しながらとりあえず公開できるところまでもっていった段階ですので、至らない点があると思います。
不備を見つけられた方はコメントで教えてくださると幸いです。
完成品はこちらです。
前提
node
はもちろん、yarn
も使いますので入れておいてください。
yarn
を使わない方は適宜、npm
で読み替えてください。
コンポーネントを作る
まずはディレクリを作って、
$ mkdir my-components-sample
$ cd my-components-sample
yarn init
してpackage.json
を作ります。
private
をfalse
にするのがポイントです。true
だと公開できないですからね。
main
は後で書き換えるので適当でいいです。
$ yarn init
yarn init v1.3.2
question name (my-components-sample):
question version (1.0.0):
question description: My Component Sample
question entry point (index.js):
question repository url:
question author:
question license (MIT):
question private: false
success Saved package.json
✨ Done in 35.73s.
vue.jsを入れます。
$ yarn add vue
適当に2つコンポーネントを作ります。
$ mkdir -p src/components
<template>
<div class="foo">
Hello Foo {{msg}}
</div>
</template>
<script>
export default {
props: {
msg: {
type: String,
required: true,
}
}
}
</script>
<style>
.foo {
color: blue;
}
</style>
<template>
<div class="bar">
Hello Bar {{msg}}
</div>
</template>
<script>
export default {
props: {
msg: {
type: String,
required: true,
}
}
}
</script>
<style>
.bar {
color: red;
}
</style>
webpack設定
webpackを設定していきます。
必要なものをまるっと追加してしましましょう。
{
"name": "my-components-sample",
"version": "1.0.0",
"description": "My Component Sample",
"main": "index.js",
"license": "MIT",
"private": false,
"dependencies": {
"vue": "^2.5.9"
- }
+ },
+ "devDependencies": {
+ "autoprefixer": "^7.1.4",
+ "babel-core": "^6.26.0",
+ "babel-loader": "^7.1.2",
+ "babel-preset-env": "^1.6.0",
+ "clean-webpack-plugin": "^0.1.17",
+ "cross-env": "^5.1.1",
+ "css-loader": "^0.28.7",
+ "style-loader": "^0.18.2",
+ "vue-loader": "^12.1.0",
+ "vue-template-compiler": "^2.3.3",
+ "webpack": "^3.6.0",
+ "webpack-merge": "^4.1.0",
+ "webpack-node-externals": "^1.6.0"
+ }
}
$ yarn install
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge')
const CleanWebpackPlugin = require('clean-webpack-plugin');
const baseConfig = {
output: {
path: path.resolve(`${__dirname}/dist/`)
},
module: {
rules: [
{
test: /\.vue$/,
use: {
loader: 'vue-loader',
}
}
]
},
resolve: {
extensions: ['.vue', '.js'],
alias: {
'@src': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src', 'components'),
'vue$': 'vue/dist/vue.esm.js'
}
},
externals: {
'vue': 'Vue'
},
plugins: [
new webpack.ProvidePlugin({
'Vue': 'vue'
})
]
};
let config;
if (process.env.NODE_ENV === 'production') {
const productionConfig = merge(baseConfig, {
plugins: [
new CleanWebpackPlugin(['dist']),
new webpack.optimize.UglifyJsPlugin({
minimize: true,
sourceMap: true,
mangle: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
],
devtool: '#source-map'
});
config = productionConfig // TODO
} else {
console.error(`\`${process.env.NODE_ENV}\` is not defined.`);
}
module.exports = config;
この状態ではまだoutput
もちゃんと指定していないし、エンドポイントもないのでコンパイルできません。
次に進みましょう。
公開する
CDNで公開する
まずはCDNで公開できるようにします。
CDN用のエンドポイントを作成します。
module.exports = {
install: function(Vue, options) {
Vue.component('foo', require('@components/Foo'));
Vue.component('bar', require('@components/Bar'));
}
};
これをエンドポイントとしたwebpackの設定を書いていきます。
- config = productionConfig // TODO
+ config = [
+ merge(productionConfig,
+ {
+ entry: path.resolve(__dirname + '/src/plugin.js'),
+ output: {
+ filename: 'my-components-sample.min.js',
+ libraryTarget: 'window',
+ library: 'MyComponentsSample'
+ }
+ })
+ ];
libraryTarget: 'window'
, library: 'MyComponentsSample'
を設定することで、ブラウザでmy-components-sample.min.js
を読み込んだときにwindow.MyComponentsSample
で使えるようになります。
package.jsonに下記を追加します。
{
...
+ "scripts": {
+ "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
+ },
...
}
すかさずビルド!
$ yarn run build
dist/my-components-sample.min.js
とdist/my-components-sample.min.js.map
ができていればOKです。
これらのファイルをCDNで公開するわけですが、これはjsDelivrを使うと超がつくほど簡単です。
まずは、packge.json
に以下を追加します。
{
...
"main": "index.js",
+ "cdn": "dist/my-components-sample.min.js",
...
}
main
は後で使うので書き換えません。
次に、今まで作ったコードをGitHubで公開しましょう。
$ git init
node_modules/
npm-debug.log
yarn-error.log
dist
ディレクトリを.gitignore
に入れないように注意です。
dist
は公開しないといけないですからね。
$ git add -A
$ git commit -m "Initial commit"
GitHubのリポジトリを作成する部分は省略します。
$ git remote add origin git@github.com:you/my-components-sample.git
$ git push -u origin master
タグも付けてあげます。
$ git tag v1.0.0
$ git push origin v1.0.0
なんと、これだけでCDNでの公開ができてしまっています。
実際にjsbinで確認してみましょう。
やりました。ちゃんと動いています。
(vue.js 2.0.3ではなぜかエラーになって動かなかったので最新バージョンのvue.jsを使っています。)
NPMで公開する
次に、NPMで公開します。
NPM用のエンドポイントを作成します。
import MyFoo from '@components/Foo';
import MyBar from '@components/Bar';
export const VERSION = '1.0.0';
export const Foo = MyFoo;
export const Bar = MyBar;
これをエンドポイントとしたwebpackの設定を書いていきます。
config = [
merge(productionConfig,
{
entry: path.resolve(__dirname + '/src/plugin.js'),
output: {
filename: 'my-components-sample.min.js',
libraryTarget: 'window',
library: 'MyComponentsSample'
}
- })
+ }),
+ merge(productionConfig,
+ {
+ entry: path.resolve(__dirname + '/src/index.js'),
+ output: {
+ filename: 'my-components-sample.js',
+ libraryTarget: 'umd',
+ library: 'MyComponentsSample',
+ umdNamedDefine: true
+ }
+ }),
];
yarn run build
を実行してdist/my-components-sample.js
とdist/my-components-sample.js.map
ができていればOKです。
あとはpackage.json
を書き換えます。
- "main": "index.js",
+ "main": "dist/my-components-sample.js",
あとは、npm に push するだけです。
npmのアカウント作成部分は省略します。
npmを汚さないために今回は実際にはpushしません。
$ yarn publish
うまく行っていれば、以下のようにして使うことができるはずです。
$ yarn add my-components-sample
<script>
import * as My from 'my-components-sample'
export default = {
components: {
'my-foo': My.Foo
}
};
</script>
落ち穂拾い
デプロイを楽にする
デプロイ手順は以下のようになります。
-
package.json
とindex.js
のバージョン書き換え yarn run deploy
git add -A && git commit -m 'hogehoge'
git tag v1.x.x && git push origin v1.x.x
yarn publish
毎回これをやるのは面倒なので半自動化しましょう。
deploy.sh
を作ります(著者はshellが苦手なのでソースが汚いのは勘弁)。
GEEEN="\e[0;32m"
RED="\e[0;31m"
RESET="\e[0m"
VERSION=$1
# Check version format
if [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] ; then
printf "${GEEEN}Deploy version v$VERSION\n${RESET}"
else
printf "${RED}VERSION format is 'x.x.x'. ($VERSION)\n${RESET}"
exit 1
fi
# Check existing tag
git tag | grep v$VERSION > /dev/null
if [ $? -eq 0 ]; then
printf "${RED}git tag 'v$VERSION' is existing\n${RESET}"
exit 1
fi
printf "${GEEEN}Rewite src/index.js\n${RESET}"
gsed -r -i "s/VERSION = '[0-9]+\.[0-9]+\.[0-9]+'/VERSION = '$VERSION'/g" src/index.js
git add src/index.js
printf "${GEEEN}Rewite package.json\n${RESET}"
gsed -r -i "s/\"version\": \"[0-9]+\.[0-9]+\.[0-9]+\"/\"version\": \"$VERSION\"/g" package.json
git add package.json
printf "${GEEEN}Build\n${RESET}"
yarn run build
git add dist
printf "${GEEEN}git commit\n${RESET}"
git commit -m "Upgrade to v$VERSION"
git tag v$VERSION
printf "${GEEEN}Please command 'git push origin master && git push origin v$VERSION && yarn publish'\n${RESET}"
実行権限をつけるのを忘れずに。
$ chmod 774 deploy.sh
これを実行するためにはmacの場合gnu-sed
が必要です。
$ brew install coreutils
$ brew install gnu-sed
Linuxの場合はgsed
をsed
に置き換えればいいと思います(たぶん)。
package.json
にdelpoyコマンドを追加してあげましょう。
"scripts": {
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
+ "deploy": "./deploy.sh"
},
あとは、yarn run deploy 1.0.0
などと実行すれば、最後のpushの直前までやってくれます。
ドキュメントを書く
せっかく、ライブラリを公開したのですから使ってもらうようにドキュメントを書くといいでしょう。
vue.jsのコンポーネントのドキュメントを書くのにはpropdocを使うのが良さそうです。
propdoc用にコンポーネントを加筆しましょう。
<script>
export default {
+ name: "Foo",
+ introduction: "displaoy message.",
+ description: `
+ This is amazing component.
+ `,
+ token: "<foo msg='ALL OK'></foo>",
props: {
msg: {
type: String,
required: true,
+ note: 'message'
}
}
};
</script>
これは以下のように使います。
<template>
<div class="component-doc">
<article v-for="doc in docs">
<h1>{{doc.name}}</h1>
<h2>{{doc.introduction}}</h2>
</article>
</div>
</template>
<script>
import propDoc from 'propdoc'
import * as My from 'my-components-sample'
export default {
data: ->
docs: [
propDoc.getDoc(My.Foo),
propDoc.getDoc(My.Bar),
]
}
</script>
もっと詳しく知りたい人は公式を確認して見てください。
まとめ
コンポーネントライブラリを作るのは結構かんたんなのでみんさんもオレオレライブラリを作って公開しましょう。
著者もRhoaというライブラリを作っています。楽しいです。