こんにちはjunです。最近の自社開発では息を吸うようにNuxt.jsやVue.js、React.jsなどを使用しています。私もそれらのJSライブラリをよく使用するのですが、使いは初めて1年ほどにして「もっとJSライブラリやNode.jsの開発をしっかり理解しないと」 という場面が増えてきました。
VueやNuxt、Reactなどは特に、ライブラリ自身のチュートリアルやインストール時のセットアップが充実しすぎてwebpack.config.jsさえ見ることもなくなりました。すぐに開発できるのが強みですが、弊害として
といったことが生じています。フレームワークやライブラリは便利ですが、簡単でもいいので構成の概念を知っておくと細かいカスタマイズや環境構築ができるようになります。
VueやReactを使わないプロジェクトなんてざらにありますし、webpackの設定ができるだけでもフロントエンドの開発でできることが違ってきます。数回に分けてwebpackを使用した以下のパターンに分けて環境構築解説をしていきたいと思います。
それではまず基礎編から初めていきます。
まずwebpackとはについて解説します。webpackは静的モジュールバンドラーというもので、複数のJSファイルなどを1つのファイルにまとめることができます。1つにまとめることで
などが見込まれます。Browserifyというものなど、他にもバンドラーはありますが今は性能的、機能的にもwebpackがかなり主流になっています。
タスクランナー的な使い方も可能であり、watchして差分だけビルドして開発するなんてことも可能です。
公式ドキュメントにもある通り、構築において以下の概念が重要となります。
今のところ特にパッとしなくてもいいので、上記にあげた5パターンを再現するためにはこの概念が必要であること、そしてその通りに設定していることを頭に入れておいてください。
まずはSassとかは忘れて、複数のJSファイルとモジュールの連携をやってみましょう。新しくディレクトリを作成してnpm initします。
npm init
npm install -D webpack webpack-cli
webpackは開発時しか使わないので -DをつけてdevDependenciesに入れます。インストール後にはnode_moduelsが作成されます。そして以下のディレクトリとファイルを作成します。
├── dist #作成
├── index.html #作成
├── node_modules
├── package-lock.json
├── package.json
├── webpack.config.js
└── src #作成
├── functions.js #作成
└── main.js #作成
開発しているときはmain.js
とfunctions.js
に記述していきます。functions.js
には共通の関数的な物を書き、モジュールとしてはおなじみのjquery
をインストールしておきます。
npm install jquery --save
index.htmlを適当に以下のようにしておきます。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>webpackの練習</title>
</head>
<body>
<main>
<div id='app'>
</div>
</main>
</body>
<script src='./bundle.js'></script>
</html>
それでmain.jsは適当にこうしておきましょう。
import $ from 'jquery';
$('#app').text('hello world')
node_modules
からjQueryをインポートして、index.html
を操作します。しかし今のままではバンドルされていないので、main.jsの内容は利用できません。webpack.config.js
を設定して、main.js
をビルドしてみましょう。
webpack.config.js
を以下のように設定してみましょう。
module.exports = {
//バンドル対象のファイル
entry: `./src/main.js`,
mode:"development",
// ファイルの出力設定
output: {
// 出力ファイルのディレクトリ名
path: `${__dirname}/dist`,
// 出力ファイル名
filename: "bundle.js"
}
};
ここで先ほどの5つの概念を思い出してください。Entry、Output、Modeの設定が書かれています。パスはwebpack.config.js
から見たパスになります。エントリーはsrc配下のmain.js
、吐き出し先は同じ階層のdist
にbundle.js
という名前で吐き出します。
module.exports
はnode.js
のモジュールとして利用するために必要です。webpackはnode.jsの環境下でビルドを行うからです。
設定が終わったらpackage.json
に以下の内容を付け足しておきます。
"scripts": {
"build": "npx webpack-cli build", #これ
"test": "echo \"Error: no test specified\" && exit 1"
},
npm run build
を叩くとwebpack
のバンドルが走ります。それではやってみましょう。
npm run build
> webpack_parctice@1.0.0 build /Users/junjiishii/Desktop/my_apps/webpack_parctice
> webpack
asset bundle.js 323 KiB [emitted] (name: main)
runtime modules 937 bytes 4 modules
cacheable modules 282 KiB
./src/main.js 54 bytes [built] [code generated]
./node_modules/jquery/dist/jquery.js 282 KiB [built] [code generated]
webpack 5.28.0 compiled successfully in 234 ms
jqueryがきちんとnode_modulesから読み込まれいます。そしてdist
配下を見るとbundle.jsができています。bundle.js
の中身をみてみますと、
わお。必要なjsファイルが一つにまとめられているので、こうなっています。main.js一行とjqueryがくっついています。それではindex.htmlをみてみると..
はい。main.js
でhello worldを入れたのできちんとmain.js
とjquery
がバンドルされ、動作していることが確認されました。
先程はnode_modules
のjquery
をインポートして利用してみました。次はfunctions.js
の関数群をインポートして利用できるようにしてみましょう。index.html
、main.js
、functions.js
を以下のように変更します。
<!-- body のみ見せます -->
<body>
<main>
<div id='app'></div>
<input type="text" value="" id="inputs">
<button id="submmit" >追加する</button>
</main>
</body>
import $ from 'jquery';
export default {
addNewText(to,input){
let text = $(input).val();
$(to).append('<p>'+text+'</p>'); #XSSできちゃうので本番では使わないように。。
$(input).val('');
}
}
import $ from 'jquery';
import funcs from './functions';
$('#submmit').on('click',()=>{
return funcs.addNewText('#app','#inputs');
})
functions.jsには便利関数を入れているのを想定しているので、オブジェクトに関数を入れておきます。それをexportします。addNewText()
は指定した入力フォームの文字列を、指定したDOMにpタグとして入れてくれる神メソッドです。TODO LIST的な物を開発していると思ってください。
main.js
ではimport funcs from './functions';
で読み込みます。funcs
というのはオブジェクトなのでfuncs.addNewText()
で使用できます。イベントリスナーでボタンを押したら追加できるようにしてみましょう。
ビルドしたら再度index.html
をみてみます。
入力内容を入れて、追加するを押すとこのように文字が追加されました。webpackが各ファイルのimportの関係性を解決してくれるので、これで複数ファイルのバンドルができるようになりました。
jsのコードを書いてビルドしたらスクリプトにエラーが起きていたという時、毎回ビルドするのは面倒です。webpackにはwatchモードという物があり、変更を検知して差分ビルドをしてくれます。package.json
に以下のように記述します。
"scripts": {
"build": "npx webpack-cli build",
"watch": "npx webpack-cli watch", #これ
"test": "echo \"Error: no test specified\" && exit 1"
},
これでnpm run watch
を行うことでwatch
モードでビルドが動くようになります。
Webpackは基本的にjsファイルのバンドルを想定していますが、css・sassもバンドルできます。今回はsassの説明をします。
webpackがsassをバンドルしてビルドするには
の4つのdevDependenciesが必要になります。
sass-loaderは重要な概念に出てきた「loader」に該当します。webpackがsassファイルをバンドルするのに必要です。node-sassはnode.jsでsassのコンパイルをするために必要です。sassをコンパイルして生成されたcssを扱うためにcss-loader、mini-css-extract-pluginが必要です。そのためまずはインストールしてみましょう。
npm install -D sass-loader node-sass css-loader mini-css-extract-plugin
ひとまず入れられたら、webpack.config.jsを以下のように変更します。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
//バンドル対象のファイル
entry: './src/js/main.js',
mode:"development",
// ここから追加
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: { url: false }
},
'sass-loader'
]
}
]
},
// ファイルの出力設定
output: {
// 出力ファイルのディレクトリ名
path: `${__dirname}/dist`,
// 出力ファイル名
filename: "bundle.js"
},
// ここも追加
plugins: [
new MiniCssExtractPlugin({
filename:'style.css'
})
]
};
srcにsassのディレクトリを作成し、そしてややこしいのでjsのフォルダも作りました。
.
├── dist
│ ├── index.html
├── package-lock.json
├── package.json
├── src
│ ├── js
│ │ ├── functions.js
│ │ └── main.js
│ └── sass
│ ├── component.scss
│ ├── style.scss
│ └── variable.scss
└── webpack.config.js
sassの3ファイルは以下のような構成になっています。
$base_color:red;
$box_size:30px;
.box{
background-color: $base_color;
width: 20px;
height: 20px;
}
@import './variable.scss';
@import './component.scss';
index.html
もバンドルされたstyle.css
を読み込むようにしましょう。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>webpackの練習</title>
<!-- これ -->
<link rel="stylesheet" href="./style.css">
</head>
<body>
<main>
<div id='app'>
</div>
<input type="text" value="" id="inputs">
<button id="submmit" >追加する</button>
<div class='box'></div>
</main>
</body>
<script src='./bundle.js'></script>
</html>
そしてエントリーファイルであった./src/js/main.js
に以下のようにscssをインポートします。
import $ from 'jquery';
import funcs from './functions';
import '~/sass/style.scss';
$('#submmit').on('click',()=>{
return funcs.addNewText('#app','#inputs');
})
こうするとwebpackが~/sass/style.scss
のインポートを捉え、適切にバンドルしてくれます。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
...
...
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: { url: false }
},
'sass-loader'
]
}
]
},
...
plugins: [
new MiniCssExtractPlugin({
filename: 'style.css'
})
]
webpack.config.js
では特にこの箇所が重要になります。module
の中身でsassや画像などのファイルを取り扱えるようになります。rules
という箇所に取り扱うファイルの拡張子を正規表現で捉え、それに対するローダーの使用などを定義します。
MiniCssExtractPlugin
はcssをstyle.cssのような外部ファイルとして出力するために必要なプラグインです。main.js
にてimport '~/sass/style.scss';
という記述があったと思います。このプラグインを使わない場合、webpackでのcssバンドルは外部ファイルでなく、HTMLに直接インライン記述をしようとします。(そうした方が処理と通信が早くなるらしい)
しかし外部ファイルstyle.css
として今回は出力したいので、MiniCssExtractPlugin
を用いてmain.js
のimport '~/sass/style.scss';
のインポートを参考に、dist配下にstyle.css
を出力します。ように外部ファイルとして出力します。MiniCssExtractPlugin
のローダーとプラグインに記述しておきます。プラグインの箇所では出力ファイル名を指定します。filename: 'style.css'
としていますが、指定しない場合はエントリーファイルのmain.js
からmain.css
が出力されます。
以上でsassのバンドルができるようになりました。早速やってみます。
npm run build
するとdistにstyle.cssができました。中身をみてみるとsassで定義した依存性や変数が当てはまっています。
以上がwebpackを用いたjsファイルのバンドルとsassのコンパイルです。大切なのは5つの概念と必要なモジュールを読み込み、設定することです。次回は忌まわしきIEでjsが動くようにすること、画像の依存性解決、複数条件のバンドルを解説します。
コメント
コメント読み込み中..