Gulpからwebpackに環境を移した際、別ファイルで定義した変数を使用できないということがあったので、その際の対応方法をメモ。
対応前
まずは対応前の各ファイルです。
package.json
{ 〜略〜 "devDependencies": { "globule": "^1.3.4", "html-webpack-plugin": "^5.5.0", "pug": "^2.0.4", "pug-loader": "^2.4.0", "webpack": "^5.73.0", "webpack-cli": "^4.10.0" } }
webpack.config.js
const path = require("path"); const globule = require('globule'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpackConfig = { entry: path.resolve(__dirname, "src", "js", "main.js"), output: { path: path.resolve(__dirname, "htdocs"), filename: "assets/js/main.js" }, module: { rules: [ { test: /\.pug$/, use: { loader: 'pug-loader', options: { pretty: true, root: path.resolve(__dirname, "src", "pug"), } } } ] }, plugins: [] }; const pugPaths = globule.find({ src: ['src/pug/**/*.pug', '!src/pug/**/_*.pug'] }); pugPaths.forEach(function(pugPath) { const filename = pugPath.replace('src/pug/', '').replace('.pug', '.html'); webpackConfig.plugins.push( new HtmlWebpackPlugin({ template: pugPath, filename, minify: false }) ) }); module.exports = webpackConfig;
pugファイルの構成は以下のようになっています。
- src
- pug
- _include
- _config.pug
- _head.pug
- _layout.pug
- index.pug
- _include
- pug
src/pug/_include/_config.pug
- var siteName = 'サイト名'; - var siteDomain = 'https://example.com';
src/pug/_include/_layout.pug
block variables include /_include/_config.pug doctype html html(lang="ja") head block head include /_include/_head.pug body block content
src/pug/_include/_head.pug
meta(charset="UTF-8") meta(http-equiv="X-UA-Compatible" content="IE=edge") meta(name="viewport" content="width=device-width, initial-scale=1.0") meta(name="format-detection" content="telephone=no") unless metaTitle - var thisPageTitle = ''; else - var thisPageTitle = metaTitle; unless metaDescription - var thisPageDescription = ''; else - var thisPageDescription = metaDescription; unless path - var thisPageUrl = siteDomain; else - var thisPageUrl = siteDomain + path; title #{thisPageTitle} meta(name="description" content=thisPageDescription) meta(property="og:site_name" content=siteName) meta(property="og:title" content=thisPageTitle) meta(property="og:description" content=thisPageDescription) meta(property="og:url" content=thisPageUrl) meta(property="og:image" content=siteDomain + '/assets/img/common/ogp.png') meta(property="og:type" content='website')
src/pug/index.pug
extends /_include/_layout.pug append variables - var metaTitle = 'トップタイトル'; - var metaDescription = 'トップ説明文'; - var path = '/'; block content p トップページ
この状態でコンパイルを行いましたが、_config.pugやindex.pugで設定した変数が_head.pugでうまく読み込めていませんでした。
<title></title> <meta name="description" content=""> <meta property="og:site_name"> <meta property="og:title" content=""> <meta property="og:description" content=""> <meta property="og:url"> <meta property="og:image" content="undefined/assets/img/common/ogp.png"> <meta property="og:type" content="website">
対応方法
pugのオプションでglobalsを設定すればいいようです。
const path = require("path"); const globule = require('globule'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpackConfig = { entry: path.resolve(__dirname, "src", "js", "main.js"), output: { path: path.resolve(__dirname, "htdocs"), filename: "assets/js/main.js" }, module: { rules: [ { test: /\.pug$/, use: { loader: 'pug-loader', options: { globals: ["SITE", "PAGE"], pretty: true, root: path.resolve(__dirname, "src", "pug"), } } } ] }, plugins: [] }; const pugPaths = globule.find({ src: ['src/pug/**/*.pug', '!src/pug/**/_*.pug'] }); pugPaths.forEach(function(pugPath) { const filename = pugPath.replace('src/pug/', '').replace('.pug', '.html'); webpackConfig.plugins.push( new HtmlWebpackPlugin({ template: pugPath, filename, minify: false }) ) }); module.exports = webpackConfig;
今回はSITE と PAGEという変数を使えるようにしました。
変数毎にglobalsに設定していくと煩雑になるため、_config.pugで設定しているサイト全体で使用する変数を「SITE」、ページ個別で設定する変数を「PAGE」にまとめる想定にしています。
次に_config.pugの設定をSITEを使った形に変更します。
- SITE = {}; - SITE.name = 'サイト名'; - SITE.domain = 'https://example.com';
index.pugも同じくPAGEを使った形に変更します。
extends /_include/_layout.pug append variables - PAGE = {}; - PAGE.metaTitle = 'トップタイトル'; - PAGE.metaDescription = 'トップ説明文'; - PAGE.path = '/'; block content p トップページ
これで変数の設定はできたので、_head.pugで読み込む変数を変更します。
meta(charset="UTF-8") meta(http-equiv="X-UA-Compatible" content="IE=edge") meta(name="viewport" content="width=device-width, initial-scale=1.0") meta(name="format-detection" content="telephone=no") unless PAGE.metaTitle - var thisPageTitle = ''; else - var thisPageTitle = PAGE.metaTitle; unless PAGE.metaDescription - var thisPageDescription = ''; else - var thisPageDescription = PAGE.metaDescription; unless PAGE.path - var thisPageUrl = SITE.domain; else - var thisPageUrl = SITE.domain + PAGE.path; title #{thisPageTitle} meta(name="description" content=thisPageDescription) meta(property="og:site_name" content=SITE.name) meta(property="og:title" content=thisPageTitle) meta(property="og:description" content=thisPageDescription) meta(property="og:url" content=thisPageUrl) meta(property="og:image" content=SITE.domain + '/assets/img/common/ogp.png') meta(property="og:type" content='website')
これで再度コンパイルを試してみると、意図した通りに変数の値が出力されていました。
<title>トップタイトル</title> <meta name="description" content="トップ説明文"> <meta property="og:site_name" content="サイト名"> <meta property="og:title" content="トップタイトル"> <meta property="og:description" content="トップ説明文"> <meta property="og:url" content="https://example.com/"> <meta property="og:image" content="https://example.com/assets/img/common/ogp.png"> <meta property="og:type" content="website">
コメントが承認されるまで時間がかかります。