LoginSignup
1
0

More than 3 years have passed since last update.

webpack4 で sass/tsファイル群を変換&バンドルしてhtmlと一緒に別フォルダに配置する

Last updated at Posted at 2020-05-05

はじめに

webpackの名前位しか知らない状態から、以下やりたかったことができる状態にできたため、webpackの設定方法等散らばっていた情報をざっくり本記事にまとめる。

  • 自身で作成したscss/tsファイルをそれぞれ1ファイル(css/js)にまとめて(バンドルして)、別のフォルダに配置
    • tsファイル:自動フォーマット → jsに変換かつ es5にトランスパイル → bundle.js生成/配置
    • scss/cssファイル:scssをcssに変換 → style.css生成/配置
    • htmlファイル:htmlも一緒に配置

できたもの をgithubに置いているため必要あればご参照ください

※諸事情により今回はフレームワークやライブラリを使用しないため対象外

webpack 導入

npm使用

npm init -y
npm i -D webpack webpack-cli

webpack 実行(小規模サンプル)

例:app.js と user.js をまとめて dist 下に bundle.js として配置

  • 実行コマンド ※面倒なら PATH を通す
.\node_modules\.bin\webpack
  • webpack.config.js 設定例
// output.pathに絶対パスを指定する必要
const path = require("path");

module.exports = {
  // モードの設定
  mode: "development",
  // エントリーポイントの設定
  entry: "./src/js/app.js",
  // 出力の設定
  output: {
    // 出力ファイル名
    filename: "bundle.js",
    // 出力先パス(絶対パス要)
    path: path.join(__dirname, "dist/js"),
  },
};
  • フォルダ構成
.
├─dist
│  │  index.html
│  │
│  └─js
│        bundle.js
│
└─src
    └─js
        │  app.js
        │
        └─model
               user.js
  • app.js
import getUser from "./model/user";

function component() {
  const element = document.createElement("div");
  const user = getUser();
  element.innerHTML = ["Hello", "webpack", user].join(" ");
  return element;
}
document.body.appendChild(component());
  • user.js
export default function getUser() {
  return "user";
}

webpack.config.js 

webpackの設定ファイル。自作する必要がある

webpack.config.js
module.exports = {
  // 中身の主な設定項目は以下参照
};

設定項目と指定の仕方を簡単に以下にまとめる。

mode モード指定

mode: "development"; // "production" / "none"

entry エントリポイント指定

バンドル対象のメインとするファイル

・単一指定

entry: "./src/index.js",

// ↓ と解釈される
// entry : {
//   main: "./src/index.js"
// }

・複数指定も可能

const { join } = require("path")

entry: {
  app1: join(__dirname, "src/app1/index.js"),
  app2: join(__dirname, "src/app2/index.js"),
  app3: join(__dirname, "src/app3/index.js"),
}

devtool ソースマップ設定

ソースマップの追加方法等を指定

devtool: "source-map",

webpack devtool ソースマップ まとめ

output バンドルファイル設定

設定項目

  • filename : 出力ファイル名
  • path : 出力ディレクトリ(絶対パス)
entry: "./src/index.js",
output: {
  filename: 'bundle.js',
  path: path.join(__dirname, 'dist'),
},
entry: "./src/index.js",
output: {
  filename: '[name].js',
  path: path.join(__dirname, 'dist'),
},
// → main.jsが出力される
entry: "./src/index.js",
output: {
  filename: '[name].js',
  path: path.join(__dirname, 'dist'),
},
// → app.jsが出力される

externals バンドル対象から除外

externals: {
  "react": "React",
  "react-dom": "ReactDOM"
},

※必要なら、ライブラリをバンドル対象から外して html に直指定

module.rules モジュール適用

設定項目

  • test : 適用対象にするファイル
  • use : (インストールした)モジュール適用。※下から上の順番に適用される。

以下、モジュールごとの設定例をまとめる。

JavaScript

babel(es5にトランスパイル)

npm install -D babel-loader @babel/core @babel/preset-env
module: {
  rules: [
    {
      test: /\.js$/,
      use: [
        {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env", {"modules": false}],
          },
        },
      ],
    },
  ],
},

babel loader 使い方

ESlint(JS用静的検証ツール)

※JSに対するESlintは非検証。

npm install -D eslint eslint-loader
{
  // enforce: 'pre'を指定することによって
  // enforce: 'pre'がついていないローダーより早く処理が実行される
  // 今回はbabel-loaderで変換する前にコードを検証したいため、指定が必要
  enforce: 'pre',
  test: /\.js$/,
  exclude: /node_modules/,
  loader: 'eslint-loader'
}

TypeScript

TypeScript 使用には設定ファイル(tsconfig.json)作成要。設定項目等は以下見れば良さそう

Typescript の tsconfig.json の簡単作成方法と設定について

  • tsconfig.json 簡易例
{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es5", // TSはECMAScript 5に変換
    "module": "es2015" // TSのモジュールはES Modulesとして出力
  }
}

awesome-typescript-loader

npm i -D typescript awesome-typescript-loader
module: {
  rules: [
    {
      test: /\.tsx?$/,
      exclude: /node_modules/,
      use: "awesome-typescript-loader",
    },
  ];
},
resolve: {
  // 拡張子を配列で指定
  extensions: [".ts", ".tsx", ".js"],
},

ts-loader

※ts-loader より awesome-typescript-loader の方が速いとか

npm i -D typescript ts-loader
module: {
  rules: [
    {
      test: /\.ts$/,
      exclude: /node_modules/,
      use: "ts-loader",
    },
  ],
},
resolve: {
  // 拡張子を配列で指定
  extensions: [".ts", ".js"],
},

TSLint(TS用静的検証ツール)非推奨

npm i -D tslint tslint-loader
module: {
  rules: [
    {
      enforce: "pre",
      test: /\.tsx?$/,
      use: [
        {
          loader: "tslint-loader",
          options: {
            typeCheck: true,
            fix: true,
          },
        },
      ],
    },
  ];
}

ESLint

TypeScriptでもESLintの使用推奨

npm install -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser prettier eslint-config-prettier eslint-plugin-prettier

webpackでの設定は、tslintとほぼ同じなため割愛

eslintの設定は .eslintrc.jsonに記述(以下サンプル)

eslintrc.json
{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "plugins": [
    "@typescript-eslint",
    "prettier"
  ],
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "sourceType": "module",
    "project": "./tsconfig.json"
  },
  "rules": {
    "prettier/prettier": [
      "error",
      {
        /* format settings */
        "singleQuote": true,
        "semi": true,
        /* lint check settings */
        "max-len": [
          "warning",
          {
            "code": 100,
            "ignoreUrls": true
          }
        ],
        "quotes": [
          "warning",
          "single",
          {
            "avoidEscape": true,
            "allowTemplateLiterals": false
          }
        ]
      }
    ],
    /* lint ignore settings */
    "@typescript-eslint/no-non-null-assertion": 0,
    "@typescript-eslint/no-explicit-any": 0,
    "@typescript-eslint/ban-types": 0
  }
}

・ESLint+Pritter参考記事
- 脱TSLintして、ESLint TypeScript Plugin に移行する
- Prettierことはじめ

Sass/CSS

scssファイルをjsにバンドルする流れ

sassをjsにバンドル.png
最新版で学ぶ webpack 4 入門 スタイルシート(CSS/Sass)を取り込む方法

Sass/CSS を JS にバンドル

npm i -D sass-loader sass style-loader css-loader

・style-loader : 動的に link タグに出力
・css-loader : css を JS にバンドル。css の url()や@import 文は js の require()に変換
・sass-loader : Sassをcssに変換する

※js に使用する css を import する必要あり

// import 文を使ってstyle.cssファイルを読み込む。
import "./style.css";
  • webpack.config.js
module: {
  rules: [
    // Sassファイルの読み込みとコンパイル
    {
      test: /\.scss/, // 対象となるファイル名
      // ローダー名指定
      use: [
        "style-loader",
        // CSSをバンドルする機能
        {
          loader: "css-loader",
          options: {
            // CSS内のurl()メソッドを取り込むか否か
            url: false,
            // ソースマップの利用有無
            sourceMap: true,

            // 0 => no loaders (default);
            // 1 => postcss-loader;
            // 2 => postcss-loader, sass-loader
            importLoaders: 2,
          },
        },
        // Sassをバンドルするための機能
        {
          loader: "sass-loader",
          options: {
            // ソースマップの利用有無
            sourceMap: true,
          },
        },
      ],
    },
  ];
}
url-loader (全画像バンドル) 使用時
module: {
  rules: [
    {
      test: /\.scss/,
      use: [
        "style-loader",
        {
          loader: "css-loader",
          options: {
            // 要true
            url: true,
            sourceMap: true,
            importLoaders: 2,
          },
        },
        {
          loader: "sass-loader",
          options: {
            sourceMap: true,
          },
        },
      ],
    },
    {
      // 対象となるファイルの拡張子
      test: /\.(gif|png|jpg|eot|wof|woff|woff2|ttf|svg)$/,
      // 画像をBase64として取り込む
      loader: "url-loader",
    },
  ];
}

※一部の画像をバンドルしたくない場合 (url-loader で limit)

※画像をバンドルせずそのまま配置したい場合 (file-loader)

ベンダープレフィックス自動付与したい場合

・ postcss-loader : css でネストした書き方をプレーンな css にする
・ css-loader と sass-loader の間に追加する

module: {
  rules: [
    {
      test: /\.scss$/i,
      use: [
        {
          loader: MiniCssExtractPlugin.loader,
        },
        {
          loader: 'css-loader',
        },
        {
          loader: 'postcss-loader',
          options: {
            plugins: [
              require('autoprefixer')({
                //browsers: ["last 2 versions", "> 1%", "ie >= 10"],
                grid: true,
              }),
            ]
          }
        },
        {
          loader: 'sass-loader',
          options: {
            sassOptions: {
              outputStyle: 'expanded',
            },
          },
        },
      ]
    },
  ]
},

※package.json or .browserslistrc に autoprefixer / babel 等を使ってコンパイルするときに対応させるブラウザを指定

{
  "browserslist": ["last 2 version", "> 1%", "ie >= 10"]
}

.browserslistrc で対象ブラウザを指定する

plugins プラグイン適用

CSS を JS と分ける (MiniCssExtractPlugin)

  • MiniCssExtractPlugin
    • CSS のバンドルを分ける(デフォルトは js に css もバンドルされる)
    • バンドルした JS から 任意のテキストを 別ファイルに出力できる

mini-css-extract-plugin 公式

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

plugins: [
  new MiniCssExtractPlugin({
    filename: 'bundle.css',  // 出力ファイル名
    path: path.join(__dirname, 'dist'),  // 出力先フォルダ
  })
],
  • css + mini-css-extract-plugin の場合
module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        // CSSファイルを書き出すオプションを有効にする
        {
          loader: MiniCssExtractPlugin.loader,
        },
        // CSSを読み込む
        'css-loader',
      ],
    },
  ],
},
plugins: [
  new MiniCssExtractPlugin({
    filename: 'style.css',  // 出力ファイル名
  }),
],
  • sass + mini-css-extract-plugin の場合
module: {
  rules: [
    {
      test: /\.scss/, // 対象となるファイルの拡張子
      use:
        [
          // CSSファイルを書き出すオプションを有効にする
          {
            loader: MiniCssExtractPlugin.loader,
          },
          {
            loader: 'css-loader',
            options: {
              url: false,
              sourceMap: true,

              // 0 => no loaders (default);
              // 1 => postcss-loader;
              // 2 => postcss-loader, sass-loader
              importLoaders: 2,
            },
          },
          {
            loader: 'sass-loader',
            options: {
              // ソースマップの利用有無
              sourceMap: true,
            },
          },
        ],
    },
  ],
},
plugins: [
  new MiniCssExtractPlugin({
    filename: 'style.css',  // 出力ファイル名
  }),
],

HTML も コンパイルして配置 (HtmlWebpackPlugin)

htmlファイルに、<script src="bundle.js"><link href="style.css" rel="stylesheet"> 等を自動追加した上で、出力先フォルダに配置できるみたい

npm i -D html-webpack-plugin html-loader
module: {
  loaders: [
    {
      test: /\.html$/,
      loader: "html-loader"
    }
  ]
},
plugins: [
  // index
  new HtmlWebpackPlugin({
    template: "./html/index.html"
  }),
  // その他
  new HtmlWebpackPlugin({
    filename: "admin.html",
    template: "./html/admin.html"
  })
]

webpack モード指定実行

  • package.json に以下指定
{
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production",
    "watch": "webpack --mode development --watch --color --progress"
  },
  :
}
  • 実行コマンド
npm run dev
npm run build
npm run watch 
  • webpack.config.js

※development モードの時だけソースマップを入れるようにすることでデバッグ等で原因箇所を追いやすくする

module.exports = (env, argv) => {
  const isDevMode = argv.mode === "development";

  return {
    mode: argv.mode,
    devtool: isDevMode ? "source-map" : "none",
    // 設定内容省略
  };
};

TypeScript フォーマッター設定 (TSLint + Prettier)

npm i -D prettier tslint tslint-loader tslint-plugin-prettier tslint-config-standard tslint-config-prettier

・tslint-config-standard : JavaScript Standard Style を使用する
・tslint-plugin-prettier : TSLint を Prettier と連携する
・tslint-config-prettier : TSLint と Prettier のルール衝突回避(Prettier のルール優先)

  • tslint.json
{
  "rulesDirectory": ["tslint-plugin-prettier"],
  "extends": ["tslint-config-standard", "tslint-config-prettier"],
  "rules": {
    "prettier": [
      true,
      {
        "singleQuote": false,
        "semi": true
      }
    ]
  }
}

rules.prettier の設定項目

  • webpack.config.js の内容
module: {
  rules: [
    {
      enforce: "pre",
      test: /\.tsx?$/,
      use: [
        {
          loader: "tslint-loader",
          options: {
            typeCheck: true,
            fix: true,
          },
        },
      ],
    },
    {
      test: /\.tsx?$/,
      exclude: /node_modules/,
      use: "awesome-typescript-loader",
    },
    {
      enforce: "pre",
      test: /\.js$/,
      use: "source-map-loader",
    },
  ];
}

TSLint と Prettier の衝突している設定確認したい場合

  • 実行コマンド
npm run tslint-check
  • package.json
{
  "scripts": {
    "tslint-check": "tslint-config-prettier-check ./tslint.json"
  }
}

※ tsconfig.json に以下がないと、エラー「TS2307: Cannot find module 'source-map'.」が起きる

{
  "compilerOptions": {
    "moduleResolution": "node"
  }
}

解決方法

TSLint + Prettier 情報元

詳細以下に記載あったため、必要あればご参照されたし(情報元に感謝を)

TypeScript + TSLint + Prettier + Webpack 環境を作成したときのメモ

TSLint を使う TypeScript プロジェクトにコードフォーマッタ Prettier を導入する

できたもの

githubに一式置いているため必要あればご参照ください。

  • srcフォルダ下は自身で作成したファイル群
  • webpack実行(npm run dev or npm run build)でdistフォルダ下のファイル自動生成して配置される
    • tsファイル:自動フォーマット → jsに変換かつ es5にトランスパイル → bundle.js生成/配置
    • scss/cssファイル:scssをcssに変換 → style.css生成/配置
    • htmlファイル: <script src="bundle.js">, <link href="style.css">が追加された状態のindex.html生成/配置
.
├─dist
|  bundle.js  
|  index.html
|  style.css
└─src
    │  index.html
    │
    ├─css
    │  │  style.scss
    │  │
    │  ├─foundation
    │  │    normalize.css
    │  │
    │  ├─layout
    │       layout.scss
    │  
    └─ts
        │  app.ts
        │
        ├─model
             user.ts

参考サイト一覧

webpack の基本だけどハマりやすい entry の設定と[name]

webpack の基本的な使い方まとめ

Webpack 4 + Babel + Sass 環境を構築

最新版で学ぶ webpack 4 入門 JavaScript のモジュールバンドラ

webpack 入門

TypeScript+webpack 4 の環境構築まとめ(React, Vue.js, Three.js のサンプル付き)

最新版で学ぶ webpack 4 入門 スタイルシート(CSS/Sass)を取り込む方法

webpack で html ファイルも出力する

webpack チートシート

【2019 年版】webpack 4 個人的設定まとめ

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0