Webpack環境下でBootstrapを使いながら、SassやJavascriptを使って簡単なフォーム作成

環境構築

  • npm init で初期化

    ディレクトリを作り、npm initで初期化

    →package.jsonをひたすらenterでつくる

  • 必要なnpmをインストール(今回はpug、sassを使う前提)

    →一気にインストール(npm i -D パッケージ名)

npm i -D webpack@5.37.1 webpack-cli@4.7.0 webpack-dev-server@3.11.2 @babel/core@7.14.3 @babel/preset-env@7.14.2 autoprefixer@10.2.5 babel-loader@8.2.2 clean-webpack-plugin@4.0.0-alpha.0 css-loader@5.2.4 file-loader@5.0.2 html-loader@2.1.2 html-webpack-plugin@5.3.1 image-webpack-loader@7.0.1 mini-css-extract-plugin@1.3.4 postcss@8.2.15 postcss-loader@5.3.0 pug-html-loader@1.1.5 resolve-url-loader@^4.0.0 sass@1.32.13 sass-loader@11.1.1 style-loader@2.0.0 url-loader@3.0.0
  • さらに、bootstrap関連のnpmもインストール(bootstrapは4.5.3を使う前提)
npm i -D bootstrap@4.5.3 jquery@3.5.1 popper.js@1.16.0 @popperjs/core@2.9.2
  • package.jsonを整える

    →デバックが毎回面倒なので、短縮コマンドをpackage.jsonに入れておく。

  "scripts": {
    "start": "npx webpack serve --mode=development",
    "build": "webpack --mode=development",
    "build:dev": "webpack"
  },
  • package.jsonの修正形はこちら(mainファイルをリネームしているのに注意)
{
  "name": "test2",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "start": "npx webpack serve --mode=development",
    "build": "webpack --mode=development",
    "build:dev": "webpack"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.14.3",
    "@babel/preset-env": "^7.14.2",
    "animejs": "^3.2.1",
    "autoprefixer": "^10.2.5",
    "babel-loader": "^8.2.2",
    "clean-webpack-plugin": "^4.0.0-alpha.0",
    "css-loader": "^5.2.4",
    "ejs-html-loader": "^4.0.1",
    "file-loader": "^5.0.2",
    "gsap": "^3.6.1",
    "html-loader": "^2.1.2",
    "html-webpack-plugin": "^5.3.1",
    "image-webpack-loader": "^7.0.1",
    "mini-css-extract-plugin": "^1.3.4",
    "postcss": "^8.2.15",
    "postcss-loader": "^5.3.0",
    "pug-html-loader": "^1.1.5",
    "resolve-url-loader": "^4.0.0",
    "sass": "^1.32.13",
    "sass-loader": "^11.1.1",
    "style-loader": "^2.0.0",
    "url-loader": "^3.0.0",
    "vue": "^2.6.12",
    "vue-cli": "^2.9.6",
    "vue-loader": "^15.9.7",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^5.37.1",
    "webpack-cli": "^4.7.0",
    "webpack-dev-server": "^3.11.2"
  },
  "dependencies": {
    "bootstrap": "^4.5.3",
    "jquery": "^3.5.1",
    "popper.js": "^1.16.0",
    "@popperjs/core": "^2.9.2",
  }
}
  • 作業ディレクトリをつくる(dist→コンパイル後、src→コンパイル前の作業用)
  • srcフォルダ内のディレクトリをつくる

    css(オリジナルのsassを入れていく)

    →images(画像など)

    →js(オリジナルのjavascript関連)

    →templates(htmlやpugを入れる)

  • webpack.config.jsをつくる(設定ファイル)

    →ルートディレクトリにwebpack.config.jsという名前で空のjsファイルをつくる

    →コアになるwebpack.config.jsの最初の状態は以下。

const path = require('path');
module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
  },
};
  • さらに、npmでインストールしていったパッケージを入れていって、整理していったものがこちら
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'development',
  entry: {
    main: './src/js/main.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'js/main.js',
  },
  module: {
    rules: [
      {
        test: /\.js/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', { "targets": "> 0.25%, not dead" }],
              ],
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: [
          {
            // loader: 'style-loader',
            loader: MiniCssExtractPlugin.loader, // 追加
          },
          {
            loader: 'css-loader',
            options: {
              url: false,
              sourceMap: true,
              importLoaders: 2,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              sourceMap: true,
              postcssOptions: {
                plugins: ["autoprefixer"],
              },
            },
          },
          {
            loader: "sass-loader",
            // options: {
            //   sourceMap: true,
            // },
          },
        ],
      },
      {
        test: /\.(gif|png|jpg|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]',
        },
        use: [
          // {
          //   loader: 'file-loader',
          //   options: {
          //     esModule: false,
          //     name: 'images/[name].[ext]',
          //   },
          // },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
            },
          },
        ],
      },
      {
        test: /\.pug/,
        use: [
          {
            loader: 'html-loader',
          },
          {
            loader: 'pug-html-loader',
            options: {
              pretty: true,
            }
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/templates/index.pug',
      filename: "index.html",
    }),
    new CleanWebpackPlugin(),
  ],
  devtool: "source-map",
  target: ["web", "es5"],
  stats: {
    children: true,
  },
};
  • src/jsへmain.jsをつくる

    →とりあえず空で

    JavascriptjQuery デバックでじりじり修正 console.log

    →モジュール化の考え。exportの外部ファイルをimport

import costom from './costom.js';
export default () => {
}
  • 新規でindex.pugをつくる
doctype html
html
  body
    h1 My Site
    p Welcome to my super lame site.
  • Sassを使う準備

    →src/cssディレクトリにstyle.scssファイルをつくる。

    →webpack.config.jsでsassファイルがコンパイルできるように記載する

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'development',
  entry: {
    main: './src/js/main.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'js/main.js',
  },
  module: {
    rules: [
      {
        test: /\.js/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', { "targets": "> 0.25%, not dead" }],
              ],
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: [
          {
            // loader: 'style-loader',
            loader: MiniCssExtractPlugin.loader, // 追加
          },
          {
            loader: 'css-loader',
            options: {
              url: false,
              sourceMap: true,
              importLoaders: 2,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              sourceMap: true,
              postcssOptions: {
                plugins: ["autoprefixer"],
              },
            },
          },
          {
            loader: "sass-loader",
            // options: {
            //   sourceMap: true,
            // },
          },
        ],
      },
      {
        test: /\.(gif|png|jpg|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]',
        },
        use: [
          // {
          //   loader: 'file-loader',
          //   options: {
          //     esModule: false,
          //     name: 'images/[name].[ext]',
          //   },
          // },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
            },
          },
        ],
      },
      {
        test: /\.pug/,
        use: [
          {
            loader: 'html-loader',
          },
          {
            loader: 'pug-html-loader',
            options: {
              pretty: true,
            }
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: './css/style.css',
    }),
    new HtmlWebpackPlugin({
      template: './src/templates/index.pug',
      filename: "index.html",
    }),
    new CleanWebpackPlugin(),
  ],
  devtool: "source-map",
  target: ["web", "es5"],
  stats: {
    children: true,
  },
};
  • src/main.jsへsassが読み込まれるようにする
import '../css/style.scss'
  • sassの動作チェック

    →Sassのネスト構造

    →Sassの変数

    →Sassのループ

  • bootstrapが使えるようにする(sass側)

    →sass.scssにインポート

@import "~bootstrap/scss/bootstrap.scss";
  • bootstrapが使えるようにする(webpack.config.js)
const webpack = require('webpack');
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery'
    }),
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'development',
  entry: {
    main: './src/js/main.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'js/main.js',
  },
  module: {
    rules: [
      {
        test: /\.js/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', { "targets": "> 0.25%, not dead" }],
              ],
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        use: [
          {
            // loader: 'style-loader',
            loader: MiniCssExtractPlugin.loader, // 追加
          },
          {
            loader: 'css-loader',
            options: {
              url: false,
              sourceMap: true,
              importLoaders: 2,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              sourceMap: true,
              postcssOptions: {
                plugins: ["autoprefixer"],
              },
            },
          },
          {
            loader: "sass-loader",
            // options: {
            //   sourceMap: true,
            // },
          },
        ],
      },
      {
        test: /\.(gif|png|jpg|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]',
        },
        use: [
          // {
          //   loader: 'file-loader',
          //   options: {
          //     esModule: false,
          //     name: 'images/[name].[ext]',
          //   },
          // },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
            },
          },
        ],
      },
      {
        test: /\.pug/,
        use: [
          {
            loader: 'html-loader',
          },
          {
            loader: 'pug-html-loader',
            options: {
              pretty: true,
            }
          },
        ],
      },
    ],
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery'
    }),
    new MiniCssExtractPlugin({
      filename: './css/style.css',
    }),
    new HtmlWebpackPlugin({
      template: './src/templates/index.pug',
      filename: "index.html",
    }),
    new CleanWebpackPlugin(),
  ],
  devtool: "source-map",
  target: ["web", "es5"],
  stats: {
    children: true,
  },
};
  • bootstrapが使えるようにする(main.js)
import "popper.js"
import "bootstrap"

Bootstrapでフォームを組み立てる

どうしてWebpackが必要か?(座学)