Closed23

Webpack

YuriYuri

mini-css-extract-pluginを使ってCSSを書き出す

YuriYuri

ローダー設定時の注意事項

ローダーは記述順の後ろから前に実行される。
1: sass-loaderでSassをCSSにコンパイル
2: css-loaderでCSSの依存関係を解決
3: mini-css-extract-plugin.loaderでCSSファイルの書き出し
の順番で処理をする場合、記載は下記の通り。

{
  test: /\.(sc|c|sa)ss$/,
  use: [
    MiniCssExtractPlugin.loader,
    'css-loader',
    'sass-loader',
  ]
}

https://www.mitsue.co.jp/knowledge/blog/frontend/201812/27_0945.html

YuriYuri

画像の適切な置き場所

YuriYuri

画像ファイルの置き場所下記2箇所のうち、どこに画像をおくべきかの判断軸を調査した。

  • public配下直置き
  • public/bundles配下

CSSから呼び出すか否か

public/bundles配下にあるとうことはfile-loaderで画像をモジュールとして扱うように処理をしているという前提がある。

画像ファイルをモジュールとみなすことで、CSS内で画像ファイルを読み込むことができる。

💡CSSから読み込みたい画像ファイル(アイコンなど)はビルドに含める

キャッシュさせたいか否か

public配下においた画像はブラウザによってキャッシュされる。

一方、バンドルに組み込むと同じ名前で違う画像に差し替えた場合でもフィンガープリントが変更されて画像ファイル名に挿入されるので、ブラウザでキャッシュされない。
これにより画像を変更したのにユーザーがキャッシュをクリアしない限り古い画像が表示され続けるという問題を回避できる。

ファイル名にフィンガープリントが入る

public配下は画像のファイル名はそのまま

💡変更が予想されない画像に関してはpublic配下に置いてしまう

YuriYuri

devtool

YuriYuri

https://webpack.js.org/configuration/devtool/

トランスパイル後と前のコードの内容を紐付けしてデバッグしやするための設定。
エラー発生箇所がコードのどこなのかを調べられるようになる。

開発環境でのみ必要なので環境ごとの設定ファイルに記載する。

@webpack.dev.js

module.exports = merge(common, {
  mode: 'development',
  devtool: 'source-map',
})

@webpack.prod.js

module.exports = merge(common, {
  mode: 'production',
  devtool: 'none',
})

参考
https://golang.hateblo.jp/entry/webpack-devtool-source-map

YuriYuri

devtoolでsource-map を指定してビルドするとoutputフォルダ配下に出力ファイルと同じファイル名で拡張子が.js.mapのファイルが生成される。

  "index.js": "/bundles/js/index-fb9d53dd6dee1cacfe01.js",
  "index.js.map": "/bundles/js/index-fb9d53dd6dee1cacfe01.js.map"

index.js.map方がソースコードとの対応付けを定義したSourceMap。

YuriYuri

Webpackの設定を環境に応じてわける方法

YuriYuri

デフォルトの落とし穴

⚠️webpackの設定ファイルはwebpack.config.jsだが、これがなくてもwebpackコマンドは実行できる。

その場合、エントリーポイントは ./src 、アウトプットは./distとなっている。
デフォルト値を確認するには公式のこのページを参照する。

※webpack.config.jsがなくてもwebpackが実行できてしまうため、webpackの設定ファイルをいじっていて内容が反映されていない時、そもそも設定ファイルの置き場所が間違っていないかも確認しよう

※いきなり環境に応じて設定ファイルを作成した時、設定ファイルが読み込まれてないとデフォルトの値でwebpackが実行できてしまうので設定ファイルが読み込まれているかの確認は別途必要

YuriYuri

公式では共通のものと環境ごとの設定ファイルを下記のようなファイル名で作成すると記載がある。

 |- webpack.common.js
 |- webpack.dev.js
 |- webpack.prod.js

webpackディレクトリを作成して下記のようにしてもOK

 |- /webpack
    |- common.js
    |- development.js
    |- production.js

こちらの方が個人的には好き

YuriYuri

webpack.config.js以外を設定ファイルとして読み込ませる場合は--config オプションでファイルを指定する。

"scripts": {
     "dev": "webpack  --config webpack/develop.js",
     "build": "webpack --config webpack/production.js"
    },
YuriYuri

ビルドエラー: TyepScript emitted no output for ...images.d.ts.

YuriYuri

原因

declareファイルがビルド対象のディレクトリ配下にあったため

解消

|- /app
    |-javascript
        |- entries
        |- types

entryファイルをapp/javascript配下 -> app/javascript/entries 配下に変更

YuriYuri

Webpack + Vue のプロジェクトを作成するログ

YuriYuri

必要なパッケージを取得

$ yarn init
$ yarn add -D webpack webpack/cli @webpack-cli/init ebpack-dev-server

webpack/cli@webpack-cli/init の違い

設定ファイル作成

$ npx webpack-cli init

対話形式に答えるとwebpack.config.jpがルート直下に作成される。
この時Yeomanの設定ファイルである .yo-rc.json も作成される。
https://webpack.js.org/contribute/writing-a-scaffold/#about-yo-rcjson

❓Yeomanとは

一旦削除して問題ないので削除

webpack-dev-serverを設定

$ yarn add -D webpack-dev-server

@package.json

"scripts": {
    "start:dev": "webpack serve --open"
  },

@webpack.config.js

devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 8000
  },

index.htmlを表示させる

アウトプットディレクトリ直下にindex.htmlを作成

@webpack.config.js

devServer: {
    openPage: "index.html", <= 追加
}

=> yarn run start:dev 実行で http://localhost:8000/index.html が開きHtmlの内容が表示されている

YuriYuri

Vueのコンポーネントを呼び出す

1: Vueのパッケージを取得

$ yarn add vue 

2: index.htmlで読み込むjsファイルにVueのインスタンスを記述
@index.js

import Vue from "vue";

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

@index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Webpack Playground</title>
</head>

<body>
  <h1>Webpack Playground</h1>
  <div id="app">
    {{ message }}
  </div>
  <script src="./index.js"></script>
</body>
</html>

3: resolve.aliasを設定
`webpack.config.js

resolve: {
    alias: {
        'vue$': 'vue/dist/vue.esm.js',
    }
  },

💡resolve.alias
import、もしくはrequireで指定するファイル(ライブラリ)名のエイリアスを作成するための設定
https://webpack.js.org/configuration/resolve/#resolvealias
https://blog.websandbag.com/entry/2020/08/07/190655
https://qiita.com/sukezane/items/58783b5a9b771429cff2

4: vue-loaderを設定する
https://vue-loader-v14.vuejs.org/ja/

$ yarn add -D vue-loader vue-template-compiler

最初vue-loader のみインストールしてビルドしたところ下記エラーが出たためvue-template-compilerも追加した。

vue-template-compiler must be installed as a peer dependency, or a compatible compiler implementation must be passed via options

Vueのテンプレート機能をプリコンパイルするために必要な様子。

@webpack.config.js

const { VueLoaderPlugin } = require('vue-loader');

plugins: [
    new VueLoaderPlugin()
  ],

  module: {
    rules: [{
      test: /\.vue$/,
      loader: 'vue-loader'
    },

vue-loaderを使うためにはpluginとして追加してあげる必要がある。
さらにルールに拡張子が .vue のファイルに対してloaderを適用するように追記する。

YuriYuri

TypeScriptに対応させる

1: TypeScriptのパッケージを取得

$  yarn add typescript ts-loader

2:ts-loaderの設定を追加
moduleのrulesにts-loaderを追加。
Vueファイルでtsを使用したい場合はappendTsSuffixTo が必要。

module: {
    rules: [{
      test: /\.vue$/,
      loader: 'vue-loader'
    },  {
      test: /\.ts$/,
      use: [
        {
          loader: 'ts-loader',
          options: {
            // .vueファイルをtsとして監視するように追加
            appendTsSuffixTo: [/\.vue$/],
          }
        }
      ]
    },

3: tsconfig.jsonの設定
下記コマンドを使うと compilerOptions についてのコメントが記載されたファイルが生成される。

$ /node_modules/.bin/tsc --init
// npxがあれば
$ npx typescript --init

生成されたtsの設定ファイルに追記。
TypeScriptを採用する対象ファイルをincludeに記載する。
excludenode_modules も。

"include": [
    "src/**/*.ts",
    "src/**/*.vue",
  ],
  "exclude": [
    "node_modules"
  ]

このままだと下記のようなエラーが出力される。

ERROR
      TS18003: No inputs were found in config file 'tsconfig.json'. Specified 'include' paths were '["src/**/*.ts","src/**/*.vue"]' and 'exclude' paths were '["node_modules"]'.

これを回避するためには vue.d.ts という型定義ファイルを作成してincludes配下に設置する必要がある。

/* eslint-disable */
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

この型定義ファイルがないとVueをimportできず、tsの対象ファイルが1つもないということでエラーになってしまう。

これでvueファイルのscriptのlang属性にtsと書いてもコンパイルが通るようになっている。

※ TSに対応させるためにはVue.component または Vue.extend でコンポーネントを定義する。

参考
https://jp.vuejs.org/v2/guide/typescript.html

このスクラップは2023/03/26にクローズされました