Help us understand the problem. What is going on with this article?

「node.js」「npm」を使って「bootstrap」を導入するまでのまとめ

1. はじめに

1.1. 背景

「node.js」でSPA(シングル・ページ・アプリケーション)を作りたい。
それにあたって、「bootstrap」を使いたい!

1.2. 目的

「node.js」の「npm」を使って「bootstrap」を読み込むこと。

2. 「npm」で「bootstrap」の導入

早速、「npm」コマンドでbootstrapをインストールします。

2.1. 筆者の開発環境の確認

bootstrapの導入にはCDNを使うのが一番楽です。

(なんらかのHTMLにて)CDNでの導入
<!-- CSS only -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

<!-- JS, Popper.js, and jQuery -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

bootstrap
BootstrapCDN

しかし、「npm」を使ってbootstrapを導入すると、後々、CSSのカスタムに便利らしいです。
なので、今回はそちらの手法を採用します。
「npm」を使うに当たって、PCの「node.js」「npm」のバージョンを確認します。

バージョンの確認
% node -v
v12.2.0
% npm -v
6.9.0

2.2. 「npm」を初期化する

node-js-bootstrapというフォルダを作成して、npm init --forceで、package.jsonを作ります。

新規プロジェクト用のフォルダを作成し、npmを初期化
% mkdir node-js-bootstrap
% cd node-js-bootstrap 
% npm init --force
npm WARN using --force I sure hope you know what you are doing.
Wrote to ~/node-js-bootstrap/package.json:

{
  "name": "node-js-bootstrap",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

% ls
package.json

package.jsonが作られました。

2.3. 「npm」を使って「bootstrap」をインストールする

公式サイトに示されているように、npm install bootstrapを実行します。

npmでbootstrapをインストール
% npm i -S bootstrap 
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN bootstrap@4.4.1 requires a peer of jquery@1.9.1 - 3 but none is installed. You must install peer dependencies yourself.
npm WARN bootstrap@4.4.1 requires a peer of popper.js@^1.16.0 but none is installed. You must install peer dependencies yourself.
npm WARN node-js-bootstrap@1.0.0 No description
npm WARN node-js-bootstrap@1.0.0 No repository field.

+ bootstrap@4.4.1
added 1 package from 2 contributors and audited 1 package in 0.923s
found 0 vulnerabilities

jquerypopper.jsがないと怒られました。
こちらも導入しましょう。

npmによるjqueryとpopper.jsの導入
% npm i -S jquery popper.js
npm WARN node-js-bootstrap@1.0.0 No description
npm WARN node-js-bootstrap@1.0.0 No repository field.

+ popper.js@1.16.0
+ jquery@3.4.1
added 2 packages from 3 contributors and audited 3 packages in 0.979s
found 0 vulnerabilities

ここから先は、目的によって行うことが異なります。
今回は、CSSをカスタマイズできるようにするために「Webpack」を導入します。

3. 「webpack」を用いて「bootstrap」を読み込む

3.1. 「webpack」の引用

こちらのWEBサイトがとても参考になります。
このWEBページを参照して、今回必要になるWebpackを導入します。

webpackなどの導入
% npm i -D webpack webpack-cli css-loader node-sass sass-loader postcss-loader autoprefixer extract-text-webpack-plugin@next

> fsevents@1.2.11 install ~/node-js-bootstrap/node_modules/fsevents
> node-gyp rebuild

  SOLINK_MODULE(target) Release/.node
  CXX(target) Release/obj.target/fse/fsevents.o
  SOLINK_MODULE(target) Release/fse.node

> node-sass@4.13.0 install ~/node-js-bootstrap/node_modules/node-sass
> node scripts/install.js

Cached binary found at ~/.npm/node-sass/4.13.0/darwin-x64-72_binding.node

> node-sass@4.13.0 postinstall ~/node-js-bootstrap/node_modules/node-sass
> node scripts/build.js

Binary found at ~/node-js-bootstrap/node_modules/node-sass/vendor/darwin-x64-72/binding.node
Testing binary
Binary is fine
npm WARN sass-loader@8.0.0 requires a peer of sass@^1.3.0 but none is installed. You must install peer dependencies yourself.
npm WARN sass-loader@8.0.0 requires a peer of fibers@>= 3.1.0 but none is installed. You must install peer dependencies yourself.
npm WARN node-js-bootstrap@1.0.0 No description
npm WARN node-js-bootstrap@1.0.0 No repository field.

+ postcss-loader@3.0.0
+ css-loader@3.4.0
+ autoprefixer@9.7.3
+ sass-loader@8.0.0
+ webpack-cli@3.3.10
+ webpack@4.41.5
+ node-sass@4.13.0
+ extract-text-webpack-plugin@4.0.0-beta.0
added 639 packages from 338 contributors and audited 6056 packages in 17.326s
found 0 vulnerabilities

sass-loadersassfibersを欲しているようなので、これもインストールしておきましょう。

sassとfibersのインストール
% npm i -D sass fibers

> fibers@4.0.2 install ~/node-js-bootstrap/node_modules/fibers
> node build.js || nodejs build.js

`darwin-x64-72` exists; testing
Binary is fine; exiting
npm WARN node-js-bootstrap@1.0.0 No description
npm WARN node-js-bootstrap@1.0.0 No repository field.

+ fibers@4.0.2
+ sass@1.24.0
added 3 packages from 4 contributors and audited 8209 packages in 2.926s
found 0 vulnerabilities

また、ここで必要になるwebpack-cliですが、$PATHを正しく通していないと、「見つからないからインストールするよ」という無限ループになるかもしれません(私の環境ではなりました。)

に丁寧に解説されています。
私の場合は$PATHをとおして、次のところを見るようになりました。

webpack-cliの場所
% which webpack-cli
~/.nodebrew/current/bin/webpack-cli

ここに$PATHが通ればOKです。

3.2. webpackのconfigファイルの作成

まるまる引用で申し訳ないですが、こちらのファイルを参照して、webpack.config.jsを作成しましょう。

ics-creative「webpack.config.js」インターネット, https://github.com/ics-creative/170330_webpack/blob/master/tutorial-bootstrap-style-js/webpack.config.js(2020/01/01閲覧)

webpack.config.js(ics-creative)
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: 'production',
  module: {
    rules: [
      {
        // 対象となるファイルの拡張子(scss)
        test: /\.scss$/,
        // Sassファイルの読み込みとコンパイル
        use: ExtractTextPlugin.extract([
          // CSSをバンドルするための機能
          {
            loader: 'css-loader',
            options: {
              // オプションでCSS内のurl()メソッドの取り込まない
              url: false,
              // ソースマップの利用有無
              sourceMap: true,
              // Sass+PostCSSの場合は2を指定
              importLoaders: 2
            },
          },
          // PostCSSのための設定
          {
            loader: 'postcss-loader',
            options: {
              // PostCSS側でもソースマップを有効にする
              sourceMap: true,
              // ベンダープレフィックスを自動付与する
              plugins: () => [require('autoprefixer')]
            },
          },
          // Sassをバンドルするための機能
          {
            loader: 'sass-loader',
            options: {
              // ソースマップの利用有無
              sourceMap: true,
            }
          }
        ]),
      },
    ],
  },
  plugins: [
    new ExtractTextPlugin('style.css'),
  ],
  // source-map方式でないと、CSSの元ソースが追跡できないため
  devtool: "source-map"
};

現時点でのファイルはこういう配置になっているはずです。

% tree -L 1
.
├── node_modules
├── package-lock.json
├── package.json
└── webpack.config.js

3.3. 「src」フォルダと「dist」フォルダの配置

webpackは、多くのファイルをまとめて整理してくれる素敵なユーティリティです。
そのため、多くのファイルが格納されている「src」フォルダと、それらのファイルを素敵に整理する「dist」フォルダを用意する必要があります。
それらのフォルダを作りましょう。

「src」「dist」フォルダの作成
% mkdir src dist && tree -L 1
.
├── dist
├── node_modules
├── package-lock.json
├── package.json
├── src
└── webpack.config.js

3 directories, 3 files

3.4. 「index.js」の配置

こちらも、最新版で学ぶwebpack 4入門 Bootstrapをバンドルする方法の記事を丸パクリで、大変申し訳ございません。「src」配下に「index.js」と「index.scss」を保存します。

index.js
import "bootstrap";
import "./index.scss";
index.scss
@import "~bootstrap/scss/bootstrap.scss";
.
├── dist
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── index.js
│   └── index.scss
└── webpack.config.js

このように「src」の下に2つファイルが保存された形になるはずです。

3.5. 「webpack」の実行

では、早速「webpack」を実行しましょう。

webpackの実行
% webpack
Hash: 4fbcfa08db41b1bd330b
Version: webpack 4.41.5
Time: 4600ms
Built at: 2020-01-01 01:49:17
        Asset     Size  Chunks                   Chunk Names
      main.js  169 KiB       0  [emitted]        main
  main.js.map  778 KiB       0  [emitted] [dev]  main
    style.css  157 KiB       0  [emitted]        main
style.css.map  432 KiB       0  [emitted] [dev]  main
Entrypoint main [big] = main.js style.css main.js.map style.css.map
[0] ./src/index.js 42 bytes {0} [built]
[4] (webpack)/buildin/global.js 472 bytes {0} [built]
[5] ./src/index.scss 41 bytes [built]
    + 4 hidden modules

WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
  main (326 KiB)
      main.js
      style.css


WARNING in webpack performance recommendations: 
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/dist/cjs.js??ref--4-1!node_modules/postcss-loader/src/index.js??ref--4-2!node_modules/sass-loader/dist/cjs.js??ref--4-3!src/index.scss:
    Entrypoint undefined = extract-text-webpack-plugin-output-filename
    [0] ./node_modules/css-loader/dist/cjs.js??ref--4-1!./node_modules/postcss-loader/src??ref--4-2!./node_modules/sass-loader/dist/cjs.js??ref--4-3!./src/index.scss 591 KiB {0} [built]
        + 1 hidden module

生成されたmain.jsファイルが、244KiBより大きいので注意されていますが、現時点では放置しておきましょう。

4. 「index.html」の作成

では、distディレクトリ以下に、簡単なindex.htmlを作成して、正しく動いているか確認します。

index.html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="stylesheet" href="./style.css" />

    <title>Hello, world!</title>
  </head>
  <body>
    <div class="container">
      <h1>Hello, world!</h1>

      <div class="card text-white bg-primary">
        <div class="card-body">
           カードのレイアウトを表示
        </div>
      </div>
    </div>
    <script src="./main.js"></script>
  </body>
</html>

正しくCSSが読まれていれば、下の画像のように表示されると思います。

2020-01-01 WEBページ例.png

一方、正しく読み込めていなければ、次のように悲しいページになるはずです。

2020-01-01 WEBページ例-2.png

4.2. index.scssの編集

では、webpackを導入した理由にあった、カスタマイズをさせてみたいと思います。
先に作成した「src」下の「index.scss」を書き換えます。

index.scss
$theme-colors: (
"primary": #b0c4de
);
@import "~bootstrap/scss/bootstrap.scss";

そして、webpackを実行すると、CSSが更新されます。
その結果、WEBページを更新すると、次のような画面に変わるでしょう。

2020-01-01 WEBページ例-3.png

SASSについては、公式サイト:Bootstrap テーマで丁寧に解説されているので参照すると良いでしょう。

4.3. Javascript の確認

CSSの確認ばかりしていて、JavaScriptが正しく動いているかを確認していませんでした。
簡単に確認してみましょう。

次の公式サイトから拾ってきたコードを、index.html<body>内のどこかに貼り付けます。

index.htmlに追記
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

2020-01-01 WEBページ例-4.png

すると、正しく動いていることが確認できると思います。

5. おわりに

ここまで書いてきたことより、「node.js」「npm」を使って「bootstrap」を導入し、実際に動いている(読み込めている)様子を確認できたこと、また、SASSを編集して自作テーマを作ることができる可能性も見えたと思います。

しかし、これで終わりではありません。SASSを編集してオリジナルのテーマを作るだけならば、node.jsを動かさなくとも、rubyなどでもできるのですから。
これらを「React」「Express」などと組み合わせて動かすことができることで、素敵なSPAが作れることでしょう。気づきがあり次第、また、Qiitaに投稿したいと思います。

参考WEBサイト

hiroseabook
MAX/MSP, Processing, SuperCollider, Ruby, PHP, Python, MySQL, Swift など。 —————— だったが、最近はもっぱら、「WordPress」と「Vue.js」(とTypeScript、SCSS)
http://hiroshi-nagayama.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした