• 最終更新日:

webpack5の設定方法 - EJS、TypeScript、Dart SassとAutoprefixer、ESLint、Prettierを自動化する

webpack 5の設定方法 - Dart SassやAutoprefixer、Babel、画像の圧縮などを自動化する

今回はwebpack5でTypeScriptとDart Sass、Autoprefixer、EJS、ESLintとPrettierなどの設定方法について説明します。

設定する内容は以下です。

  • EJS
  • Dart Sass
  • CSSのAutoprefixerの設定
  • TypeScript
  • AirbnbでESLintのルールを強化
  • ESLintとPrettierの設定
  • 開発サーバーの立ち上げ、ホットリロード
  • ライセンス情報をjsファイルの中に含める

説明する環境は以下です。

  • macOS Catalina v10.15.5
  • Visual Studio Code v1.57.0
  • webpack v 5.50.0
  • node.js v16.13.1
この記事の目次

webpack 5の設定方法

サイト制作で必要な基本的なwebpackの設定です。
TypeScriptやPugを使ってサイト制作する方は以下の記事を合わせて参照してみてください。Babelの設定方法についても紹介しています。

ファルダ構成について

以下の画像にある【src】フォルダは作業スペースで、そこで作業した内容が【dist】フォルダに出力さます。

【src】と【dist】の中を見てみると、以下のようになっています。

webpackをインストールする

webpackをインストールする前に、プロジェクトの設定情報に必要なpackage.jsonを準備します。VSCodeを使っているなら【control + shift + @】でターミナルが表示されるので、以下のコマンドを打ってpackage.jsonを作成します。

npm init -y

package.jsonが作成できたら、以下のコマンドをターミナルで打ってwebpackをインストールします。

npm i -D webpack webpack-cli

webpack 5で使うパッケージをインストールする

今回の設定では以下のパッケージが必要になるので、1行ずつインストールしていきます。

npm i -D html-loader #HTML読み込み用
npm i -D html-webpack-plugin #HTML用
npm i -D template-ejs-loader #EJS読み込み用
npm i -D ts-loader #TypeScript読み込み用
npm i -D typescript #TypeScript
npm i -D mini-css-extract-plugin #CSSの出力用
npm i -D css-loader #CSS読み込み用
npm i -D sass #Sass #Sass
npm i -D sass-loader #Sass読み込み用
npm i -D postcss-loader #Autoprefixerの設定用
npm i -D autoprefixer #Autoprefixer
npm i -D eslint  #ESLint用
npm i -D eslint-config-prettier #prettierと競合するルールをオフ
npm i -D eslint-config-airbnb-base #ESLintにAirbnbのルール拡張
npm i -D eslint-config-airbnb-typescript #ESLintにAirbnb TypeScriptのルール拡張
npm i -D eslint-plugin-import #importするファイルの拡張子問題解決
npm i -D eslint-plugin-unused-imports #使っていないimportは削除
npm i -D prettier #Prettier用
npm i -D copy-webpack-plugin #画像をコピー用
npm i -D webpack-dev-server #仮想サーバー立ち上げ用
npm i -D terser-webpack-plugin #パッケージのライセンス情報をjsファイルの中に含める
npm i -D webpack-watched-glob-entries-plugin #読み込むファイルを複数指定する
npm i -D @typescript-eslint/eslint-plugin #ESLintがTypeScriptを理解できるようにする
npm i -D @typescript-eslint/parser #ESLintがTypeScriptを理解できるようにする

webpackも含めて、一括でインストールする場合は以下のように1行で書きます。

npm i -D webpack webpack-cli html-loader html-webpack-plugin template-ejs-loader ts-loader typescript mini-css-extract-plugin css-loader sass sass-loader postcss-loader autoprefixer eslint eslint-config-prettier eslint-config-airbnb-base eslint-config-airbnb-typescript eslint-plugin-import eslint-plugin-unused-imports prettier copy-webpack-plugin webpack-dev-server terser-webpack-plugin webpack-watched-glob-entries-plugin @typescript-eslint/eslint-plugin @typescript-eslint/parser

インストールができるとpackage.jsonにパッケージ名とバージョンが載っているので確認してみましょう。以下は例です。

一部のパッケージがインストールできない場合

パッケージの依存関係が解決できず、エラーになってパッケージがインストールできない場合があります。インストールできないパッケージについては、以下のコマンドで強制的にインストールすることは可能です。ただ、互換性を無視するため動作の確認は必要になります。

npm i --legacy-peer-deps 【パッケージ名】

詳しくはこちらの記事を参照してください。

webpack.config.jsに設定を書く

webpackの設定を書くために、webpack.config.jsというファイルを作成して以下の内容を書きます。

//path モジュールの読み込み
const path = require('path');
//cssファイルの出力用
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
//パッケージのライセンス情報をjsファイルに含める
const TerserPlugin = require('terser-webpack-plugin');
//画像のコピー用
const CopyPlugin = require('copy-webpack-plugin');
// HTMLの読み込み用
const HtmlWebpackPlugin = require('html-webpack-plugin');
//読み込むファイルを複数指定する用
const WebpackWatchedGlobEntries = require('webpack-watched-glob-entries-plugin');
//EJS用
const { htmlWebpackPluginTemplateCustomizer } = require('template-ejs-loader');

const enabledSourceMap = process.env.NODE_ENV !== 'production';

const filePath = {
  js: './src/js/',
  ejs: './src/ejs/',
  sass: './src/scss/',
};

/* Sassファイル読み込みの定義*/
const entriesScss = WebpackWatchedGlobEntries.getEntries([path.resolve(__dirname, `${filePath.sass}**/**.scss`)], {
  ignore: path.resolve(__dirname, `${filePath.sass}**/_*.scss`),
})();

const cssGlobPlugins = (entriesScss) => {
  return Object.keys(entriesScss).map(
    (key) =>
      new MiniCssExtractPlugin({
        //出力ファイル名
        filename: `./css/${key}.css`,
      })
  );
};

/* EJS読み込みの定義 */
const entries = WebpackWatchedGlobEntries.getEntries([path.resolve(__dirname, `${filePath.ejs}**/*.ejs`)], {
  ignore: path.resolve(__dirname, `${filePath.ejs}**/_*.ejs`),
})();
const htmlGlobPlugins = (entries) => {
  return Object.keys(entries).map(
    (key) =>
      new HtmlWebpackPlugin({
        //出力ファイル名
        filename: `${key}.html`,
        //ejsファイルの読み込み
        template: htmlWebpackPluginTemplateCustomizer({
          htmlLoaderOption: {
            //ファイル自動読み込みと圧縮を無効化
            sources: false,
            minimize: false,
          },
          templatePath: `${filePath.ejs}${key}.ejs`,
        }),

        //JS・CSS自動出力と圧縮を無効化
        inject: false,
        minify: false,
      })
  );
};

/* TypeScript読み込みの定義 */
const entriesTS = WebpackWatchedGlobEntries.getEntries([path.resolve(__dirname, `${filePath.js}*.ts`)])();

const app = {
  entry: entriesTS,
  //出力先(デフォルトと同じなので省略可)
  output: {
    filename: './js/[name].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
  //仮想サーバーの設定
  devServer: {
    //ルートディレクトリの指定
    static: path.resolve(__dirname, 'src'),
    hot: true,
    open: true,
  },
  //パッケージのライセンス情報をjsファイルの中に含める
  optimization: {
    minimizer: [
      new TerserPlugin({
        extractComments: false,
      }),
    ],
  },
  module: {
    rules: [
      {
        test: /\.ejs$/i,
        use: ['html-loader', 'template-ejs-loader'],
      },
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        // 対象となるファイルの拡張子(scss)
        test: /\.(sa|sc|c)ss$/,
        // Sassファイルの読み込みとコンパイル
        use: [
          // CSSファイルを抽出するように MiniCssExtractPlugin のローダーを指定
          {
            loader: MiniCssExtractPlugin.loader,
          },
          // CSSをバンドルするためのローダー
          {
            loader: 'css-loader',
            options: {
              //URL の解決を無効に
              url: false,
              // production モードでなければソースマップを有効に
              sourceMap: enabledSourceMap,
              // postcss-loader と sass-loader の場合は2を指定
              importLoaders: 2,
              // 0 => no loaders (default);
              // 1 => postcss-loader;
              // 2 => postcss-loader, sass-loader
            },
          },
          // PostCSS(autoprefixer)の設定
          {
            loader: 'postcss-loader',
            options: {
              // PostCSS でもソースマップを有効に
              sourceMap: enabledSourceMap,
              postcssOptions: {
                // ベンダープレフィックスを自動付与
                plugins: [require('autoprefixer')({ grid: true })],
              },
            },
          },
          // Sass を CSS へ変換するローダー
          {
            loader: 'sass-loader',
            options: {
              //  production モードでなければソースマップを有効に
              sourceMap: enabledSourceMap,
            },
          },
        ],
      },
    ],
  },
  // import 文で .ts ファイルを解決するため
  // これを定義しないと import 文で拡張子を書く必要が生まれる。
  resolve: {
    // 拡張子を配列で指定
    extensions: ['.ts', '.js'],
  },
  target: 'web',
  //プラグインの設定
  plugins: [
    ...cssGlobPlugins(entriesScss),
    ...htmlGlobPlugins(entries),
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, 'src/images/'),
          to: path.resolve(__dirname, 'dist/images'),
        },
      ],
    }),
  ],
  //source-map タイプのソースマップを出力
  devtool: 'source-map',
  // node_modules を監視(watch)対象から除外
  watchOptions: {
    ignored: /node_modules/, //正規表現で指定
  },
};

module.exports = app;

TypeScriptの指定を書く

TypeScriptをJavaScriptにトランスパイルする指定をtsconfig.jsonに書きます。ターミナルで以下のように打つとtsconfig.jsonが作成されます。

tsc --init

作成されたtsconfig.jsonを見てみるといろいろ書かれていますが、重要な指定は以下です。

{
  "compilerOptions": {
    "target": "es5", //ES5に変換
    "module": "es2015", //モジュールをES Modulesとして出力
    "sourceMap": true, //soucemapを出力する
    "strict": true, //厳格な型チェック機能を有効にする
    "moduleResolution": "node", //node_modules からライブラリを読み込む
    "esModuleInterop": true, //CommonJS 形式のモジュールを、ES Modules でインポートできるようにする
    //以下はお好みで。
    "skipLibCheck": true, //型システムの精度を犠牲にすることで、コンパイル実行時間を削減
    "forceConsistentCasingInFileNames": true //import時にファイルパスの文字列で大文字小文字を区別するかどうか
  }
}

Autoprefixerの指定を書く

package.jsonにAutoprefixerの指定を追記します。今回は以下のように設定しました。IE11はサポートが終了したので除外しています。ここはお好みで。

  • > 3% in JP
  • not ie 11
  • last 1 versions

package.jsonを開いて以下のように書きます。

"browserslist": [
    "> 3% in JP",
    "not IE 11",
    "last 1 versions"
  ],

ESLintの設定

ESLintはコードにあるバグを見つけてくれたり、インデントやスペースなどコードスタイルに一貫性を持たせてくれるものです。

まずは.eslintrc.jsにという名前でファイルを作って設定を書いていきます。

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'airbnb-base',
    'airbnb-typescript/base', 
    'plugin:@typescript-eslint/recommended', //型を必要としないプラグインの推奨ルールをすべて有効
    'plugin:@typescript-eslint/recommended-requiring-type-checking', //型を必要とするプラグインの推奨ルールをすべて有効
    'prettier', //追加 ESLintの情報に沿ってフォーマット
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 12, //latestから12に変更
    sourceType: 'module',
    tsconfigRootDir: __dirname, //追加 tsconfig.jsonがある相対パスを指定
    project: ['./tsconfig.json'], //追加  tsconfig.jsonを指定
  },
  plugins: ['@typescript-eslint', 'unused-imports'],
  /*-- ↓以下ルール --*/
  rules: {
    'no-use-before-define': 'off', //関数や変数が定義される前に使われているとエラーになるデフォルトの機能をoff
    '@typescript-eslint/no-use-before-define': ['error'], //typescript側のno-use-before-defineを使うようにする
    'import/prefer-default-export': 'off', //named exportがエラーになるので使えるようにoff
    '@typescript-eslint/no-unused-vars': 'off', //unused-importsを使うため削除
    'unused-imports/no-unused-imports': 'error', //不要なimportの削除
    'unused-imports/no-unused-vars': [
      //unused-importsでno-unused-varsのルールを再定義
      'warn',
      { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' },
    ],
    'no-param-reassign': [2, { props: false }], //パラメーターのプロパティ変更を許可
    'import/extensions': [
      //importのときに以下の拡張子を記述しなくてもエラーにしない
      'error',
      {
        js: 'never',
        ts: 'never',
      },
    ],

    'no-void': [
      //void演算子の許可
      'error',
      {
        allowAsStatement: true,
      },
    ],
  },
  settings: {
    'import/resolver': {
      //importするファイルをjsだけではなく、tsを含むファイルを許可する
      node: {
        paths: ['src'],
        extensions: ['.js', '.ts'],
      },
    },
  },
  /*-- ↑ルールここまで --*/
};

rulesの部分をカスタマイズしたい人は以下の公式サイトを参考にしてみてください。

ESLintでチェックしなくて良いフォルダやファイルを指定する場合は、.eslintignoreというファイルを作ってそこに指定していきます。今回は出力先のdistフォルダやwebpack.config.jsは除外しています。

node_modules/
dist/
webpack.config.js
.eslintrc.js

最後にVSCodeからESLintの拡張機能をインストールして、有効化しましょう。

Prettierの設定

Prettierはコードを設定したルールに基づいて整形してくれます。どのように整形するかは.prettierrc.jsというファイルを用意してそこに書いていきます。

以下は例です。

module.exports = {
  printWidth: 120,
  trailingComma: "es5",
  tabWidth: 2,
  semi: true,
  singleQuote: true,
  endOfLine: "lf"
};

指定できるoptionについては以下の公式サイトを参考にしてみてください。

設定が書けたら、VSCodeでPrettierの拡張機能をインストールして、有効化しましょう。

VSCode上でESLintとPrettierを機能させる

ファイルを保存したタイミングでESLintとPrettierを実行させるためにはVSCode上の設定も変更する必要があります。

キーボードの【 commnad + , 】で設定画面が開かれます。そしたら以下のアイコンを押して、ESLintとPrettierに必要な設定を加えます。

設定ファイルに加える内容は以下です。

"editor.defaultFormatter": "esbenp.prettier-vscode", //VSCodeではPrettierで整形する
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true // ファイル保存時に ESLint でフォーマット
  },
"editor.formatOnSave": true, //ファイルを保存したタイミングでフォーマットする

設定が保存できたら、1度VSCodeを再起動させましょう。
これでファイルを保存したタイミングで、ESLintとPrettierが機能するようになります。

webpack.config.jsの中身を説明する

webpack.config.jsに書いた設定について、簡単に説明します。

読み込み先と出力先を指定する

webpackはjsファイルを中心に処理されていきます。そのため読み込ませるjsファイルの指定と、読み込んだ後にjsファイルを出力させる場所を指定します。

今回はTypeScriptを使うのでtsファイルを読み込み、jsファイルで出力させます。

//path モジュールの読み込み
const path = require('path');
//読み込むファイルを複数指定する用
const WebpackWatchedGlobEntries = require('webpack-watched-glob-entries-plugin');

const filePath = { //それぞれのパスを指定
  js: './src/js/',
  ejs: './src/ejs/',
  sass: './src/scss/',
};

//TypeScript読み込みの定義
const entriesTS = WebpackWatchedGlobEntries.getEntries([path.resolve(__dirname, `${filePath.js}*.ts`)])();

const app = {
  entry: entriesTS, //読み込むファイルを指定
  output: {
    filename: './js/[name].js', //どこに出力するのか指定
    path: path.resolve(__dirname, 'dist'), //出力先にフォルダを指定
    clean: true, //ビルドごとにdistフォルダの中を削除する
  },

仮想サーバーの立ち上げ

パッケージのwebpack-dev-serverを使うことで仮想サーバーを立ち上げることができます。必要な指定は以下が考えられます。(4系の場合)

  • static … 監視するフォルダを指定
  • hot … 差分ファイルのみ更新
  • open … ブラウザを立ち上げる
//仮想サーバーの設定(4系の書き方)
  devServer: {
    //ルートディレクトリの指定
    static: path.resolve(__dirname, 'src'),
    hot: true,
    open: true,
  },
  target: 'web', //targetは'web'にする

基本的には4系がオススメですが、3系を使っている場合は以下の指定が必要です。

  • contentBase … どのフォルダのファイルを表示させるか
  • open … ブラウザを自動で立ち上げるかどうか
  • watchContentBase … ファイルが更新されたら、表示も変更させるか
  • writeToDisk … 開発環境でもフォルダやファイルを出力させるかどうか
//仮想サーバーの設定(3系の書き方)
  devServer: {
    //ルートディレクトリの指定
    contentBase: path.join(__dirname, "dist"),
    //ブラウザを自動的に起動
    open: true,
    // ファイルを監視するかどうか
    watchContentBase: true,
    //バンドルされたファイルを出力するかどうか。お好みで。
    //writeToDisk: true
  },
  target: 'web', //targetは'web'にする

writeToDiskについて、指定がなければdistフォルダにはファイルもフォルダも出力されません。ただwebpack上でデータが保存されているため表示はされます。

開発している間もフォルダやファイルを出力させたいのであれば、writeToDiskをtrueにしておきましょう。

書き方の違いについては以下の記事を参考にしてみてください。

Sassの処理について

ローダーは下から順番に読み込まれて処理されていきます。下から順番にローダーを書くと以下です。

  • sass-loader … SassをCSSに変換する。ここでDart Sassを指定。
  • postcss-loader … Autoprefixerを適用させている。
  • css-loader … CSS内のurl()メソッドの取り扱いについて。
//cssファイルの出力用
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

{
   // 対象となるファイルの拡張子(scss)
   test: /\.(sa|sc|c)ss$/,
   // Sassファイルの読み込みとコンパイル
   use: [
      // CSSファイルを抽出するように MiniCssExtractPlugin のローダーを指定
      {
        loader: MiniCssExtractPlugin.loader,
       },
        // CSSをバンドルするためのローダー
       {
          loader: 'css-loader',
          options: {
          //URL の解決を無効に
          url: false,
          // production モードでなければソースマップを有効に
          sourceMap: enabledSourceMap,
          // postcss-loader と sass-loader の場合は2を指定
          importLoaders: 2,
          // 0 => no loaders (default);
          // 1 => postcss-loader;
          // 2 => postcss-loader, sass-loader
          },
        },
        // PostCSS(autoprefixer)の設定
        {
          loader: 'postcss-loader',
          options: {
            // PostCSS でもソースマップを有効に
            sourceMap: enabledSourceMap,
            postcssOptions: {
            // ベンダープレフィックスを自動付与
              plugins: [require('autoprefixer')({ grid: true })],
             },
           },
         },
          // Sass を CSS へ変換するローダー
         {
           loader: 'sass-loader',
           options: {
              //  production モードでなければソースマップを有効に
              sourceMap: enabledSourceMap,
           },
         },
     ],
},

そしてcssファイルを出力については以下で書いています。

//path モジュールの読み込み
const path = require('path');
//読み込むファイルを複数指定する用
const WebpackWatchedGlobEntries = require('webpack-watched-glob-entries-plugin');

const filePath = { //それぞれのパスを指定
  js: './src/js/',
  ejs: './src/ejs/',
  sass: './src/scss/',
};

/* Sassファイル読み込みの定義*/
const entriesScss = WebpackWatchedGlobEntries.getEntries([path.resolve(__dirname, `${filePath.sass}**/**.scss`)], {
  ignore: path.resolve(__dirname, `${filePath.sass}**/_*.scss`),
})();

const cssGlobPlugins = (entriesScss) => {
  return Object.keys(entriesScss).map(
    (key) =>
      new MiniCssExtractPlugin({
        //出力ファイル名
        filename: `./css/${key}.css`,
      })
  );
};

最後にcssGlobPlugins関数をpluginsの部分で実行します。

plugins: [
    ...cssGlobPlugins(entriesScss),
  ],

Dart Sassを使ったサイト設計については以下に書いたので参考にしてみてください。

パッケージのライセンス情報をjsファイルに含める

通常だとライセンス情報が【ファイル名】.LICENSE.txtのようにテキストファイルで出力されます。ファイルを出力させず、jsファイルの中にライセンス情報を含めるために、terser-webpack-pluginを使用しています。

//terser-webpack-pluginの読み込み
const TerserPlugin = require("terser-webpack-plugin");

//パッケージのライセンス情報をjsファイルの中に含める
  optimization: {
    minimizer: [
      new TerserPlugin({
        extractComments: false
      })
    ]
  },

こちらの記事を参考にさせてもらいました。

HTMLの処理について

EJSで書いたファイルをHTMLとして処理します。

{
  test: /\.ejs$/i,
    use: ['html-loader', 'template-ejs-loader'],
},

そしてHTMLとして出力する指定は以下で書いています。

//path モジュールの読み込み
const path = require('path');
// HTMLの読み込み用
const HtmlWebpackPlugin = require('html-webpack-plugin');
//読み込むファイルを複数指定する用
const WebpackWatchedGlobEntries = require('webpack-watched-glob-entries-plugin');
//ejs用
const { htmlWebpackPluginTemplateCustomizer } = require('template-ejs-loader');

const filePath = { //それぞれのパスを指定
  js: './src/js/',
  ejs: './src/ejs/',
  sass: './src/scss/',
};

/* EJS読み込みの定義 */
const entries = WebpackWatchedGlobEntries.getEntries([path.resolve(__dirname, `${filePath.ejs}**/*.ejs`)], {
  ignore: path.resolve(__dirname, `${filePath.ejs}**/_*.ejs`),
})();
const htmlGlobPlugins = (entries) => {
  return Object.keys(entries).map(
    (key) =>
      new HtmlWebpackPlugin({
        //出力ファイル名
        filename: `${key}.html`,
        //ejsファイルの読み込み
        template: htmlWebpackPluginTemplateCustomizer({
          htmlLoaderOption: {
            //ファイル自動読み込みと圧縮を無効化
            sources: false,
            minimize: false,
          },
          templatePath: `${filePath.ejs}${key}.ejs`,
        }),

        //JS・CSS自動出力と圧縮を無効化
        inject: false,
        minify: false,
      })
  );
};

最後にhtmlGlobPlugins関数をpluginsで実行しています。

plugins: [
    ...htmlGlobPlugins(entries),
  ],

HtmlWebpackPluginのオプションについては以下です。

  • filename … 出力するファイル名を指定
  • template … どのファイルを読み込むか指定
  • inject … trueにするとCSSファイルとJavascriptファイルの読み込みをHTMLファイルに書いてくれる。JavaScriptファイルはheadを指定すればhead内に、bodyを設定すればbodyが閉じる前に書き込まれる。
  • minify … HTMLファイルを圧縮するかどうか

今回はtemplate-ejs-loaderを使ってEJSの読み込みとオプションの指定をしています。詳しくは公式で確認してください。

画像の取り扱いについて

画像についてはsrcフォルダにあるimagesフォルダにアップすると、distフォルダのimagesフォルダに出力されるようになります。

srcフォルダの中にあるimagesフォルダに画像が1枚もないとエラーになるので注意しましょう。

plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, 'src/images/'), //画像を読み込むフォルダを指定
          to: path.resolve(__dirname, 'dist/images'), //画像を出力するフォルダを指定
        },
      ],
    }),
  ],

webpackを動かす

webpackを動かすためにコマンドを打ちます。コマンドを省略して打てるようにpackage.jsonに以下のように書きます。

"scripts": {
    "prod": "NODE_ENV=production webpack --mode production",
    "dev": "webpack --mode development",
    "watch": "webpack --mode development --watch",
    "start": "webpack serve --mode development",
    //以下はESLintとPrettierでチェックするコマンド
    "lint": "eslint --cache --fix ./src/js/ && prettier --write ./src/"
  }
  • prod … 本番環境として出力
  • dev … 開発環境として出力
  • watch … 開発環境モードでファイルを監視する
  • start … 仮想サーバーの立ち上げて、開発環境モードでファイルを監視する
  • lint … ESLintとPrettierでコードを整形、チェックさせる

コマンドを打つときは、最初にnpm runをつけます

開発しているときは以下のコマンドで始まり、

npm run start #仮想サーバーの立ち上げて、開発環境モードでファイルを監視する

開発が終われば以下のコマンドでファイルをまとめてdistフォルダに出力する、という流れになります。

npm run prod #本番環境として出力

CSSの出力について

webpackを通してSassファイルを読み込んで、CSSファイルとして出力させます。そのため、CSSファイルを出力させるためにはtsファイルにSassファイルをimportさせる必要があります。

// Sassファイルの読み込み
import "../scss/style.scss";

あとはejsファイルの_headの.ejs中にcssを読み込ませる指定を書きます。

 <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>webpack5のサンプル</title>
    <link rel="stylesheet" href="./css/style.css" />
    <script defer src="./js/init.js"></script>
  </head>

EJSの出力について

EJSについては、srcの中にあるejsフォルダで管理しています。分割するheaderやfooterなどのファイルは「components」フォルダの中で_header.ejsや_footer.ejsのようにアンダーバーをつけて配置させます。

|_src/
   |- ejs/ (共通で使うパーツ)
   |   |- components/
   |   |   |- _header.ejs
   |   |   |- _footer.ejs
   |
   |- index.ejs

例えばindex.ejsに_header.ejsを読み込ませる場合は以下のように書きます。

<!DOCTYPE html>
<html lang="ja">
  <%- include('./components/_head.ejs'); %>
  <body>
    <div>
      <h1>テスト</h1>
      <p>テキスト</p>
    </div>
  </body>
</html>

さいごに

今回はwebpack5でTypeScriptとDart Sass、Autoprefixer、EJS、ESLintとPrettierなどの設定方法について説明しました。

webpackとgulpが比較されることが多いですが、どちらが良いというわけではなく、使いやすいほうを使えば良いです。ただ、gulp自体のシェア率が落ちているため、gulp用のプラグインの開発、メンテナンスが今後進まない可能性はあります。

ご自身が使っている言語やプロジェクトによってどちらが適しているのか使い分けてみてください。