gulpfile.jsにパッケージを追加する際、ES Modulesで作成されているため追加できないということがたまにあるので、gulpfile.jsをES Modulesでの記述に移行する方法を試してみました。
対応前
まずは移行前のpackage.jsonとgulpfile.jsの内容を確認しておきます。
package.jsonは以下の内容になっています。
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"browser-sync": "^2.27.10",
"gulp": "^4.0.2",
"gulp-plumber": "^1.2.1",
"gulp-pug": "^5.0.0",
"gulp-sass": "^5.1.0",
"sass": "^1.53.0"
}
}
gulpfile.jsは以下の内容です。
const gulp = require('gulp');
const plumber = require('gulp-plumber');
const pug = require('gulp-pug');
const sass = require('gulp-sass')(require('sass'));
const browserSync = require('browser-sync');
const src = {
root: 'src/',
pug: ['src/pug/**/*.pug', '!src/pug/**/_*.pug'],
pugbase: './src/pug',
pugwatch: 'src/pug/**/*.pug',
sass: ['./src/sass/**/*.scss', '!./src/sass/**/_*.scss'],
sasswatch: './src/sass/**/*.scss'
};
const dest = {
root: './htdocs/',
pug: './htdocs/',
css: 'htdocs/assets/css/'
};
gulp.task('pug', function() {
return gulp.src(src.pug)
.pipe(plumber())
.pipe(pug({
pretty: true,
basedir: src.pugbase
}))
.pipe(gulp.dest(dest.pug))
.pipe(browserSync.reload({stream:true}));
});
gulp.task('sass', function () {
return gulp.src(src.sass)
.pipe(plumber())
.pipe(sass.sync({
outputStyle : 'expanded'
}))
.pipe(gulp.dest(dest.css))
.pipe(browserSync.reload({stream:true}));
});
gulp.task('server', function() {
browserSync({
server: {
baseDir: dest.root,
},
startPath: '/',
});
});
gulp.task('watch', function() {
gulp.watch(src.pugwatch, gulp.task('pug'));
gulp.watch(src.sasswatch, gulp.task('sass'));
});
gulp.task('default', gulp.parallel('watch', 'server'));
srcディレクトリ内で開発用のコードを管理、htdocsディレクトリにコンパイル後のHTMLやCSSを出力する構成になっています。
設定方法
まずはgulpfile.jsをgulpfile.mjsにリネームして、require()をimportに書き換えます。
import gulp from 'gulp'; import plumber from 'gulp-plumber'; import pug from 'gulp-pug'; import dartSass from 'sass'; import gulpSass from 'gulp-sass'; const sass = gulpSass(dartSass); import browserSync from 'browser-sync'; 〜 略 〜
次に、task()を使わない形に変更します。
〜 略 〜
const pug_task = () => {
return gulp.src(src.pug)
.pipe(plumber())
.pipe(pug({
pretty: true,
basedir: src.pugbase
}))
.pipe(gulp.dest(dest.pug))
.pipe(browserSync.reload({stream:true}));
}
const sass_task = () => {
return gulp.src(src.sass)
.pipe(plumber())
.pipe(sass.sync({
outputStyle : 'expanded'
}))
.pipe(gulp.dest(dest.css))
.pipe(browserSync.reload({stream:true}));
}
const server_task = () => {
browserSync({
server: {
baseDir: dest.root,
},
startPath: '/',
});
}
const watch_task = () => {
gulp.watch(src.pugwatch, pug_task);
gulp.watch(src.sasswatch, sass_task);
}
export default gulp.parallel(watch_task, server_task);
export {pug_task as pug};
export {sass_task as sass};
export {server_task as server};
export {watch_task as watch};
次に、タスク単位で別ファイルに分割します。
taskディレクトリ内に各タスクファイルを設置する想定で、まずはパスなど共通で使用する値を格納する_config.ejsをtaskディレクトリ内に作成します。
export const src = {
root: 'src/',
pug: ['src/pug/**/*.pug', '!src/pug/**/_*.pug'],
pugbase: './src/pug',
pugwatch: 'src/pug/**/*.pug',
sass: ['./src/sass/**/*.scss', '!./src/sass/**/_*.scss'],
sasswatch: './src/sass/**/*.scss'
};
export const dest = {
root: './htdocs/',
pug: './htdocs/',
css: 'htdocs/assets/css/'
};
taskディレクトリにpug.mjs、sass.mjs、server.mjs、watch.mjsというファイルを作成して、それぞれのタスクを移行します。
pug.mjs
import gulp from 'gulp';
import plumber from 'gulp-plumber';
import pug from 'gulp-pug';
import browserSync from 'browser-sync';
import { src, dest } from "./_config.mjs";
export const pug_task = () => {
return gulp.src(src.pug)
.pipe(plumber())
.pipe(pug({
pretty: true,
basedir: src.pugbase
}))
.pipe(gulp.dest(dest.pug))
.pipe(browserSync.reload({stream:true}));
}
sass.mjs
import gulp from 'gulp';
import plumber from 'gulp-plumber';
import dartSass from 'sass';
import gulpSass from 'gulp-sass';
const sass = gulpSass(dartSass);
import browserSync from 'browser-sync';
import { src, dest } from "./_config.mjs";
export const sass_task = () => {
return gulp.src(src.sass)
.pipe(plumber())
.pipe(sass.sync({
outputStyle : 'expanded'
}))
.pipe(gulp.dest(dest.css))
.pipe(browserSync.reload({stream:true}));
}
server.mjs
import browserSync from 'browser-sync';
import { src, dest } from "./_config.mjs";
export const server_task = () => {
browserSync({
server: {
baseDir: dest.root,
},
startPath: '/',
});
}
watch.mjs
import gulp from 'gulp';
import { src, dest } from "./_config.mjs";
import { pug_task } from "./pug.mjs";
import { sass_task } from "./sass.mjs";
export const watch_task = () => {
gulp.watch(src.pugwatch, pug_task);
gulp.watch(src.sasswatch, sass_task);
}
最後に、各ファイルに移行したタスクをgulpfile.ejsにインポートして、タスクを実行できるようにします。
import gulp from 'gulp';
import { pug_task } from "./task/pug.mjs";
import { sass_task } from "./task/sass.mjs";
import { server_task } from "./task/server.mjs";
import { watch_task } from "./task/watch.mjs";
export default gulp.parallel(watch_task, server_task);
export {pug_task as pug};
export {sass_task as sass};
export {server_task as server};
export {watch_task as watch};
これでタスクの実行を試して、正しく動作することが確認できました。
うまくいかなかった例
試していてうまくいかなかった例を備忘録として残しておきます。
公式ドキュメントの情報を参考に、esmのパッケージを追加して、gulpfile.jsに前述と同じ変更を行った上でgulpfile.esm.jsとリネームして試したところ、問題なく動作しました。
ただ、その後gulp-imageminを追加してみた際、以下のようなエラーになりました。
TypeError: Invalid host defined options
調べてみるとesmのパッケージの機能サポートが部分的(import/exportのみサポート?)のようで、追加するパッケージによってはエラーが出ることもありそうだったので、今回はgulpfile.jsをgulpfile.mjsにリネームする形で対応しました。
コメントが承認されるまで時間がかかります。