ちょっとがんばるWebサイト開発 on Webpack5 - JavaScriptをコピー＆ペーストする

# 前書き

## 本記事のゴール

この記事では、ソースフォルダ `/src` および配信用フォルダ `/dist` を管理するプロジェクトにおいて、Webpackを利用して `/src` フォルダに含まれるJavaScriptファイルを `/dist` フォルダに移動させる（コピー＆ペーストする）方法を理解することを目指します[^1]。

## この記事で解説する内容

- ソースフォルダ `/src` および配信用フォルダ `/dist` の分割管理について説明します
- `/src` フォルダに含まれるHTMLファイルを `/dist` にコピー＆ペーストする方法を説明します
- 簡単な実例を示します

## この記事で解説しない内容

- HTML/CSS等JavaScript以外のファイル形式は取り扱いません

## シリーズ記事



# 背景知識

## ソースフォルダ `/src` ・配信用フォルダ `/dist`

[「ちょっとがんばるWebサイト開発 on Webpack5 - HTMLをコピー＆ペーストする」](https://qiita.com/Sharkkii/items/033e3d8119bfe60f520e#背景知識) の説明を一部改変して引用したものを載せておきます。

> 一般にプロジェクト開発では、ソースコード（開発者が手動で実装したコード）と配信用コード（利用/公開するコード）を分離して管理することがあります。例えば、C/Java言語のようにコンパイルが必要な言語を使用する場合や、ソースコードの一部または全部を非公開にしたい場合にそのような管理方法を採用します。慣例的に、ソースコードは `/src` フォルダに、配信用コードは `/dist` に格納されることが多いです。

## このシリーズ記事における設計思想

[「ちょっとがんばるWebサイト開発 on Webpack5 - HTMLをコピー＆ペーストする」](https://qiita.com/Sharkkii/items/033e3d8119bfe60f520e#背景知識) の説明を一部改変して引用したものを載せておきます。

> このシリーズ記事では、ソースコードの一部または全部に対して各種変換処理/最適化を行うことでWebサイトとして公開する配信用コードを生成することを想定します。そのため、C/Java言語のプロジェクトと同様に、ソースコードと配信用コードを分離して管理することにしています。慣例に倣って、ソースコードを `/src` フォルダに、配信用コードを `/dist` に格納しています。
>
> それに加えて、配信用コードはそのままの形で利用可能であることが望ましいと考えています。すなわち、配信用コードにはWebサイトの公開に必要なものがすべて含まれており、`/dist` ディレクトリ配下のファイル群をWebサーバにアップロードすることで完全なWebサイトになるような設計を目指します。そのため、プロジェクトのビルドの出力結果が完全なWebサイトになるように設定します。
>
> 実践的なプロジェクトでは、すべてのソースファイルに対して変換処理/最適化を行うとは限りません。例えば、ソースJavaScriptファイルをそのままの形で利用/公開したい場合もあるでしょう。そうした場合（実装したソースコードと利用/公開する配信コードが同一の場合）でも、当該ファイルを `/src` フォルダから `/dist` フォルダに移動させる（コピー＆ペースト）するようにします。それによって、Webサーバにアップロードすべきファイル/フォルダを `/dist` フォルダで統一的に管理することができるようになり、配信用コードを選別する時間的コストを削減することができます。
>
> なお、単純なファイル/フォルダのコピー＆ペーストはシェルスクリプト等によっても実現可能ですが、このシリーズ記事ではWebpackを利用して解決することにしています。ビルド作業全体をWebpackに集約することでビルドツールの管理コストも削減することができますし、新たに変換処理/最適化を適用したくなった際にも比較的容易に移行することができるためです。

# 方法

:::note info
サンプルコードをGitHubで公開しています。記事と併せてご覧ください。
**[/website/website-dev-on-webpack5/plain-js-on-webpack5](https://github.com/Sharkkii/sample-codes/tree/develop/website/website-dev-on-webpack5/plain-js-on-webpack5)**
:::

:::note info
実装例の説明では、ファイル/フォルダパスを *ルート相対パス* の形式で記述しています。ここでルートはプロジェクトルートまたはWebサイトのドキュメントルートに相当します。
:::

## 準備

Webpackを含むNode.jsパッケージの利用には [Node.js](https://nodejs.org/ja/) が必要です。
インストールが未実施の場合には、以下のリンクからインストールしておいてください。

https://nodejs.org/ja/

また、動作確認を行うためのNode.jsプロジェクトを作成しておきます。
適当な名前のディレクトリ（ここでは `my-js-project` ）を用意した上で、そのディレクトリにおいて `npm init` コマンドを実行することでNode.jsプロジェクトを新規作成することができます。

```shell:ターミナル
# my-js-projectディレクトリの作成
mkdir /path/to/my-js-project
cd /path/to/my-js-project

# Node.jsプロジェクトの作成
npm init
```

`npm init` コマンドを実行するとプロジェクトに関する情報を入力するよう促されますが、今回は適当な設定にしておいて問題ありません。今後必要に応じて適宜変更しましょう。
コマンド実行完了後、 `/package.json` という設定ファイルが新規作成されていることを確認したら事前準備完了です。

## 手順概要

1. [npmパッケージを導入する](#手順1-npmパッケージを導入する)
JavaScriptのコピー＆ペーストに必要なnpmパッケージ　`webpack` `webpack-cli` をプロジェクトに追加します。

2. [Webpackの設定ファイルを記述する](#手順2-webpackの設定ファイルを記述する)
JavaScriptをコピー＆ペーストする手順やルールを設定ファイル `/webpack.config.js` に記述します。

3. [JavaScriptファイルを作成する](#手順3-javascriptファイルを作成する)
動作確認用のJavaScriptファイルを `/src/source.js` を作成します。

4. [Webpackのビルドを実行する](#手順4-webpackのビルドを実行する)
Webpackのビルドを実行することで、JavaScriptファイル `/dist/target.js` を生成（コピー＆ペースト）します。

## 手順詳細

### [手順1] npmパッケージを導入する

今回は [Webpack](https://webpack.js.org/) を利用してJavaScriptファイルのコピー＆ペーストを行います。

まず初めに、Webpackを利用するのに必要な　`webpack` `webpack-cli` パッケージをインストールします。
Webpack5（version5.X.X）をインストールするため、バージョン指定を行っています。

https://webpack.js.org/

```shell:ターミナル
npm install --save-dev webpack@5 webpack-cli@5
```

### [手順2] Webpackの設定ファイルを記述する

Webpackは、適切に設定を記述することで様々な処理を実行することができます。
ここではJavaScriptファイル　`/src/source.js` をコピーして `/dist/target.js` にペーストするための必要最小限の設定を示します。

```js:/webpack.config.js
const path = require("path");

module.exports = function() {
  return {

    mode: "development",

    entry: {
      /**
       * /src/source.js -> OUTPUT_DIRECTORY/target.js
       */
      target: path.resolve(__dirname, "src/source.js"),
    },

    output: {
      /**
       * OUTPUT_DIRECTORY = /dist
       */
      path: path.resolve(__dirname, "dist"),
    },

  }
}
```

特に注目すべきポイントは以下の2点です。

1) **Webpackのエントリ設定箇所に、入力JavaScriptファイルのパスを指定する**
2) **Webpackの出力設定箇所に、出力JavaScriptファイルの格納先のパスを指定する**

1つ目のエントリ設定は、ソースJavaScriptファイルをWebpackのビルド対象とするために必要なものです。
Webpackは、原則としてエントリ設定で指定されたファイル群とそれが依存するファイル群をビルド対象とし、そのファイル群に対して各種最適化/変換処理を行います。
`entry: { target: path.resolve(__dirname, "src", "source.js") }` という設定を記述することで、ソースJavaScriptファイル `/src/source.js` をWebpackのビルドプロセスに入力することができ、各種最適化/変換処理の結果を配信用ディレクトリに出力することができます。

2つ目の出力設定は、ビルド作業結果の出力先を指定するために必要なものです。
`output: { path: path.resolve(__dirname, "dist") }` という設定を記述することで、ビルド作業結果を `/dist` ディレクトリに出力させることができます[^2]。

> [参考] Webpack設定
> - [Webpack - Concepts](https://webpack.js.org/concepts)
> - [Concepts | webpack #entry](https://webpack.js.org/concepts/#entry)
> - [Concepts | webpack #output](https://webpack.js.org/concepts/#output)
> - [Entry Points | webpack](https://webpack.js.org/concepts/entry-points/)
> - [Output | webpack](https://webpack.js.org/configuration/output/)

### [手順3] JavaScriptファイルを作成する

手順2の設定に従ってJavaScriptファイルを作成します。
上記設定ファイル `/webpack.config.js` では入力JavaScriptファイルパスを　`/src/source.js` に指定したので、その位置に `source.js` ファイルを作成しましょう。
ファイル内容はどんなものでも構いませんが、ここでは例として以下のように記述することにします（折りたたみ要素の中にあります）。

<details>
<summary> /src/source.js の入力内容例</summary>

```js:/src/source.js
const MESSAGE = "Hello, Webpack!";
console.log(MESSAGE);
```
</details>

### [手順4] Webpackのビルドを実行する

手順1〜3でJavaScriptのコピー＆ペーストのための準備が完了しました！
それではWebpackを用いて `/src/source.js` から `/dist/target.js` を生成（コピー＆ペースト）してみましょう。
ターミナルで `npx webpack` コマンドを実行することでビルド作業が開始します。

```shell:ターミナル
# ディレクトリ移動
cd /path/to/my-js-project

# Webpackコマンド実行
npx webpack
```

ビルドが正常に完了すれば、`/src/source.js` の実行内容を含むJavaScriptファイル `/dist/target.js` が生成されていることを確認できると思います。`/dist/target.js` の `eval("...")` の引数に `/src/source.js` の実行内容が文字列として挿入されていますが、この文字列プログラムが `eval` 関数によって間接的に実行されることで、　`/src/source.js` を直接的に実行した場合と同じ効果を得ることができます。適当なHTMLファイルを作成して `/dist/target.js` を読み込むよう指示することでそれを確認することができます[^1]。

<details>
<summary>　/dist/target.js の出力内容例</summary>

```js:/dist/target.js
/*
 * ...
 */
/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./src/source.js":
/*!***********************!*\
  !*** ./src/source.js ***!
  \***********************/
/***/ (() => {

eval("const MESSAGE = \"Hello, Webpack!\";\nconsole.log(MESSAGE);\n\n\n//# sourceURL=webpack://my-js-project/./src/source.js?");

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module can't be inlined because the eval devtool is used.
/******/ 	var __webpack_exports__ = {};
/******/ 	__webpack_modules__["./src/source.js"]();
/******/ 	
/******/ })()
;
```
</details>

# 後書き

**サンプルコード**
**[/website/website-dev-on-webpack5/plain-js-on-webpack5](https://github.com/Sharkkii/tech-blog-code/tree/develop/website/website-dev-on-webpack5/plain-js-on-webpack5)**

[^1]: 実行結果から推察できるように、この記事で紹介している方法は厳密にはJavaScriptファイルのコピー＆ペーストではなく、JavaScriptファイルの埋め込み作業です。生成結果の配信用コードがソースコードとほぼ同様の振る舞いをするよう設計されていること、同シリーズ別記事との統一性等の事情を考慮した結果、正確性を多少犠牲にして「JavaScriptファイルのコピー＆ペースト」と言うことにしました。
[^2]: この記事のWebpack設定ファイルでは省略されていますが、Webpackの出力設定では `output: { filename: ... }` という形で出力ファイルの名前を指定することができます。設定を記述しなかった場合、デフォルトではエントリ設定のエントリ名が使用されることになっています。