【npmライブラリ作成】デモページの作り方(GitHub Pages)

OSS

方針

  • デモページのコードはexamplesディレクトリで管理。
    examples/srcには開発用のコードをまとめ、examples/publicは本番用のコードを格納する。
  • デモページにはGithub Pagesを使用。examples/public/index.htmlを読み込ませる。
// Reactプロジェクトの例。React以外でも構造は同じ。
...
├─examples // デモページ用ディレクトリ
│   ├─public
│   │  ├─index.html
│   │  └─bundle.js
│   └─src
│         ├─App.tsx
│         ├─index.css
│         └─index.tsx
├─.babelrc
├─package.json
...

Github pagesの準備

Github pagesのライブラリをインストール

yarn add -D gh-pages
# or
npm install --save-dev gh-pages

Github pages公開用コマンドを追加

package.jsonにGithub pages公開用コマンドを追加します。
ここに追加しておけば、npm run deploy:demo または yarn deploy:demo を実行すれば公開できます。

今回は、-d examples/publicをオプションにつけているので、examples/publicディレクトリのindex.htmlを読み込む形になります。

{
  ...

  "scripts": {
    "deploy:demo": "gh-pages -d examples/public",
  },
  ...
}

Babelの設定

トランスパイルするための設定。使用技術に合わせてプラグインを追加してください。
今回はReactとTypeScriptを使用していたので、その分のプラグインは記載してます。
※JavaScriptを使用しないデモページには必要ありません。

yarn add -D @babel/cli @babel/core @babel/preset-env
#or
npm install --save-dev @babel/cli @babel/core @babel/preset-env

#React使用時は下記追加
yarn add -D @babel/preset-react @babel/plugin-transform-react-jsx
#or
npm install --save-dev @babel/preset-react @babel/plugin-transform-react-jsx

#TypeScript使用時は下記追加
yarn add -D @babel/plugin-transform-typescript @babel/preset-typescript
#or
npm install --save-dev @babel/plugin-transform-typescript @babel/preset-typescript

なぜトランスパイルするのか?
・JavaScriptのコードを新しい書き方から古い書き方に変換し、新しい書き方・機能をサポートしないブラウザでも動くコードに変換するため。
・JSX(React)やVueファイルをJavaScriptファイルに変換するため。JSXやVueファイルはそのままではブラウザで動かない。

バンドルツールを使う

バンドルする(複数のファイルをまとめる)ことで、ファイルのリクエスト数が減少し、ページ読み込み速度が速くなります。

webpackを使用する場合

必要パッケージインストール

yarn add -D webpack webpack-cli webpack-dev-server babel-loader css-loader html-webpack-plugin postcss-loader postcss-preset-env style-loader ts-loader fork-ts-checker-webpack-plugin
#or
npm install --save-dev webpack webpack-cli webpack-dev-server babel-loader css-loader html-webpack-plugin postcss-loader postcss-preset-env style-loader ts-loader fork-ts-checker-webpack-plugin

TypeScriptを使用していない場合は、最後の2つはインストールする必要はない(ts-loader, fork-ts-checker-webpack-plugin)。

htmlファイルを追加

webpackの場合は、srcファイルにindex.htmlを用意します。

...
├─examples // デモページ用ディレクトリ
│   ├─public // バンドルファイルを出力するディレクトリ。.gitignore指定。
   │  ├─index.html
   │  └─bundle.js
│   └─src
         ├─App.tsx
         ├─index.css
         ├─index.html // コレ。
         └─index.tsx
├─.babelrc
├─package.json
├─webpack.config.js
...
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta name="description" content="Demo for new library" />
    <title>Page Title</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

webpack.config.jsを追加

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");

module.exports = {
  entry: "./examples/src/index.tsx",
  module: {
    rules: [
      {
        test: /\.(t|j)sx?$/,
        loader: "ts-loader",
        options: {
          transpileOnly: true,
        },
      },
      {
        test:  /\.(t|j)sx?$/,
        exclude: path.resolve(__dirname, 'node_modules'),
        loader: 'babel-loader', // .babelrcの設定が読み込まれる
      },
      {
        test: /\.css$/,
        use: [
          "style-loader",
          "css-loader", 
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  ["postcss-preset-env"],
                ],
              },
            },
          },
        ],
      },
    ],
  },
  output: {
    path: path.join(__dirname, "examples/public"),
    filename: "bundle.js",
  },
  resolve: {
    extensions: ["*", ".js", ".jsx", ".ts", ".tsx"],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "examples/src/index.html"),
      filename: "./index.html",
    }),
    new ForkTsCheckerWebpackPlugin({
      typescript: true,
      eslint: {
        files: "./src/**/*.{ts,tsx}",
      },
    }),
  ],
  devServer: {
    port: 3010,
  },
};

package.jsonにスクリプト追加

npm run dev:demo / yarn dev:demo => ローカルでページ起動
npm run build:demo / yarn build:demo => ビルド

..., 
  "scripts": {
    ...,
    "dev:demo": "webpack-dev-server --config webpack.config.js --mode development",
    "build:demo": "rm -rf examples/public && webpack --config webpack.config.js --mode production"
  },
..., 
スポンサーリンク

rollupを使用する場合

必要パッケージインストール

yarn add -D rollup @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-replace rollup-plugin-postcss rollup-plugin-serve rollup-plugin-terser @rollup/plugin-typescript
#or
npm install --save rollup @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-replace rollup-plugin-postcss rollup-plugin-serve rollup-plugin-terser @rollup/plugin-typescript

TypeScriptを使用していない場合は、最後の1つ(@rollup/plugin-typescript)をインストールする必要はない。

htmlファイルを追加

rollupの場合は、バンドル後のディレクトリにindex.htmlを用意します。また、バンドルしたJSファイルを読み込ませます。

...
├─examples // デモページ用ディレクトリ
│   ├─public 
│   │  ├─index.html // コレ。
│   │  └─bundle.js // バンドルファイル。.gitignore指定。
│   └─src
│         ├─App.tsx
│         ├─index.css
│         └─index.tsx
├─.babelrc
├─package.json
├─rollup.config.js
...
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta name="description" content="Demo for new library" />
    <script defer="defer" src="bundle.js"></script> // バンドルしたJSファイルを読み込ませる
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

rollup.config.jsを追加

import resolve from "@rollup/plugin-node-resolve";
import { babel } from "@rollup/plugin-babel";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "@rollup/plugin-typescript";
import { terser } from "rollup-plugin-terser";
import postcss from "rollup-plugin-postcss";
import serve from "rollup-plugin-serve";
import replace from "@rollup/plugin-replace";

// rollupコマンドがwatchかどうかで、開発状態かビルド状態か判断する
// rollup -c -w -> watch
// rollup -c -> not watch
const watch = process.env.ROLLUP_WATCH;

const config = [
  {
    input: "examples/src/index.tsx",
    output: {
      file: `examples/public/bundle.js`,
      format: "iife", // <script>タグで読み込むのに適したフォーマット
    },
    plugins: [
      resolve(),
      replace({
        preventAssignment: true,
        "process.env.NODE_ENV": JSON.stringify("development"), // スクリプト内で指定した文字列を置換する。
      }),
      commonjs(),
      postcss(),
      typescript({ tsconfig: "tsconfig.demo.json" }), // TypeScript使用時のみ追加。tsconfigが複数ある場合はconfigファイルを指定。
      babel({
        exclude: "node_modules/**",
        babelHelpers: "bundled",
      }),
      !watch && terser(), // ビルド時はバンドルファイルをminifyする。
      watch &&
        // ローカルでページを自動的に開く。今回はexamples/public/index.htmlが読み込まれる。
        serve({
          open: true,
          verbose: true,
          contentBase: ["", "examples/public"],
          host: "localhost",
          port: 3000,
        }),
    ],
  },
];

export default config;

package.jsonにスクリプト追加

npm run dev:demo / yarn dev:demo => ローカルでページ起動
npm run build:demo / yarn build:demo => ビルド

..., 
  "scripts": {
    ...,
    "dev:demo": "rollup --config rollup.config.js --watch",
    "build:demo": "rollup --config rollup.config.js",
  },
..., 

これで準備はOK!

  • 開発時は、npm run dev:demo / yarn dev:demo で開発環境を立ち上げる。
  • デプロイ前には、npm run build:demo / yarn build:demo でビルド用ファイルを準備する。
  • デプロイ時は、npm run deploy:demo / yarn deploy:demo でGithub Pageにデプロイ。

スクリプトは好みに応じて名前を変えたり、まとめたりしてもOKです。

タイトルとURLをコピーしました