【CSS + JS】テキストの無限ループアニメーション
gulp4 + webpack4でつくるフロント開発環境
今回はフロントエンドの開発環境についてのメモ。gulp
やwebpack
などの環境設定について。
まだgulp?
gulpってもう古くない?まだ使ってんの?
ってツッコミがありそうですが、僕の開発環境ではまだまだ現役です!
gulp.jsから卒業!や、もういらない!など、検索するといろいろな記事が出てきますが、個人的にはJSとCSSさえビルドできればなんでも一緒です。
そうなるとますますgulpじゃなくてもええやん。ってなりそうですが、
昔から特にgulpで消耗したこともないですし、他に変えるコストを考えるとバージョン上げて使い続ける方が楽だったので使い続けています。
とは言え、gulpを使っていてもフロントの開発環境はすぐに新しくなって変わっていくので、古くなったサイトの環境が今と合わなくてよく開発環境の立ち上げ方や使い方を忘れたりします。
そんなときのために今の開発環境を備忘録として残しておこうと思いました。
開発環境の構成
【2020.07.28】node v14.5.0で動かしています。
現状つかっている構成はこんな感じ.
gulpfile.babel.js
├── /tasks
├── browsersync.js
├── css.js
├── html.js
├── img.js
├── js.js
├── svg.js
└── watch.js
├── config.js
├── index.js
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
.babelrc
package.json
では詳しくみていきます。
package.json
こちらは扱うモジュールの依存関係を記載しています。yarn
やnpm
でインストールするとdevDependencies
に記載のあるパッケージがnode_module
にインストールされます。
{
//・・・基本設定部分省略
"scripts": {
"dev": "NODE_ENV=development gulp",
"production": "NODE_ENV=production gulp",
"build": "NODE_ENV=production gulp build"
},
"devDependencies": {
"@babel/core": "^7.7.0",
"@babel/plugin-proposal-optional-chaining": "^7.10.4",
"@babel/plugin-transform-runtime": "^7.6.2",
"@babel/polyfill": "^7.7.0",
"@babel/preset-env": "^7.7.1",
"@babel/preset-react": "^7.7.0",
"@babel/register": "^7.7.0",
"@babel/runtime": "^7.7.1",
"@barba/core": "^2.7.2",
"@barba/css": "^2.1.12",
"@barba/prefetch": "^2.1.8",
"autoprefixer": "^9.7.1",
"babel-loader": "^8.0.6",
"browser-sync": "^2.26.7",
"css-mqpacker": "^7.0.0",
"del": "^5.1.0",
"exports-loader": "^1.1.0",
"gulp": "^4.0.2",
"gulp-base64": "^0.1.3",
"gulp-cached": "^1.1.1",
"gulp-csso": "^4.0.1",
"gulp-diff-build": "^1.0.2",
"gulp-if": "^3.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-notify": "^3.0.0",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^8.0.0",
"gulp-progeny": "^0.4.1",
"gulp-rename": "^2.0.0",
"gulp-sass": "^4.0.1",
"gulp-sass-glob": "^1.0.9",
"gulp-svgmin": "^3.0.0",
"gulp-webp": "^4.0.1",
"gulp.spritesmith": "^6.11.0",
"imagemin-jpegtran": "^7.0.0",
"imagemin-mozjpeg": "^9.0.0",
"imagemin-pngquant": "^9.0.0",
"imports-loader": "^1.1.0",
"intersection-observer": "^0.11.0",
"jquery": "^3.4.1",
"jquery.easing": "^1.4.1",
"lazysizes": "^5.1.2",
"lodash": "^4.17.4",
"node-sass": "^4.13.0",
"object-fit-images": "^3.2.3",
"picturefill": "^3.0.2",
"pngquant": "^3.0.0",
"postcss-assets": "^5.0.0",
"postcss-cssnext": "^3.0.2",
"postcss-flexbugs-fixes": "^4.1.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0",
"terser-webpack-plugin": "^3.0.7",
"through2": "^4.0.2",
"uglifyjs-webpack-plugin": "^2.0.0",
"vinyl": "^2.1.0",
"vinyl-named": "^1.1.0",
"vinyl-source-stream": "^2.0.0",
"webpack": "^4.41.2",
"webpack-encoding-plugin": "^0.3.1",
"webpack-merge": "^5.0.9",
"webpack-stream": "^5.1.1"
},
"dependencies": {
"core-js": "3.6.5",
"css-loader": "^4.0.0",
"regenerator-runtime": "^0.13.3",
"sass-loader": "^9.0.2"
}
}
今回紹介するCSSとJSのビルドに必要なものだけをピックアップしました。
それでも多いですよね・・・まぁ多くても少なくても個人的にはあまり関係ないっちゃないのですが、依存しているプラグインが多いと、そのうちのどれかのプラグインの開発が終わってしまったときに問題が起こるかもしれません。
.babelrc
ES6で書きたいので.babelrc
にbabelの設定を書いて gulpfile.js
をgulpfile.babel.js
にしています。
.babelrc
の中身はこちら
{
"presets": [
["@babel/preset-env", {
"targets": {
"node": "current",
"browsers": ["last 2 versions"]
},
"useBuiltIns": "entry",
"corejs": 3
}]
],
"plugins": ["@babel/plugin-proposal-optional-chaining"]
}
polyfillの適用など基本的なbabelの設定です。
こちらの設定内容については今回は省略します。
gulpfile.babel.jsをファイル分割
gulpfile.babel.js
はファイルではなくディレクトリにして直下にindex.js
を配置します。これは数年前にどこかで見た記事を参考にしたのですが、よく調べると公式ドキュメントに書いてありました。
この方法を使うとgulp実行する際にgulpfile.babel.js/index.js
を読み込んでくれるので、タスクごとにファイル分割して管理しやすくなります。
こちらがそのindex.js
の中身です。
import gulp from 'gulp';
import { watcher } from './tasks/watch';
import { deleteCssDir, buildCss } from './tasks/css'
import { deleteJsDistDir, buildJs, buildJsAll } from './tasks/js'
import { browsersync } from './tasks/browsersync'
//Default
exports.default = gulp.series(watcher, browsersync);
//build CSS&JS
exports.build = gulp.series(deleteCssDir, deleteJsDistDir, buildCss, buildJsAll);
タスクはgulpfile.babel.js/tasks
以下にそれぞれの役割ごとにファイル分割して設置。 ← require-dir
モジュールでディレクトリ内の全てのファイルを読み込みます。gulp.task()
の書き方が非推奨になっていたのでrequire-dir
は使用をやめ、import
で必要なタスクのみを読み込むようにしました。
タスクを読み込んだらdefault
タスクを書いておきます。ここではwatcher
とbrowsersync
というタスクを直列でgulp起動時に実行するようにしています。直列というのはwatcher
→browsersync
という順番に実行するということです。
設定ファイル(config.js)について
gulpfile.babel.js
内にあるconfig.js
について。
gulpfile.babel.js
├── /tasks
├── browsersync.js
├── css.js
├── html.js
├── img.js
├── js.js
├── svg.js
└── watch.js
├── config.js <= こちらのファイル
├── index.js
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
.babelrc
package.json
こちらには主にフォルダやファイルのパスや、glob(ワイルドカードでファイル名のセットを指定するパターン)を指定したものなどをまとめているファイルです。
中身はこんな感じです。
import path from 'path'
//各パス設定
export const paths = {
serverDir : 'notes.sharesl.net',
themeDir : path.join(__dirname, '../'),
imageDir : path.join(__dirname, '../assets/images'),
imageminDir : path.join(__dirname, '../assets/imagemin'),
spriteDir : path.join(__dirname, '../assets/sprite'),
spriteminDir : path.join(__dirname, '../assets/spritemin'),
jsSrcDir : path.join(__dirname, '../assets/js'),
jsDistDir : path.join(__dirname, '../assets/dist'),
sassDir : path.join(__dirname, '../assets/sass'),
cssDir : path.join(__dirname, '../assets/css'),
svgDir : path.join(__dirname, '../assets/svg'),
svgminDir : path.join(__dirname, '../assets/svg'),
jsEntryFileName : 'entry.js'
}
//ファイルマッチパターン
export const globs = {
html : `${paths.themeDir}**/*.(html|php)`,
svg : `${paths.svgDir}/**/*.svg`,
img : `${paths.imageDir}/**/*.+(jpg|jpeg|png|gif|svg)`,
sprite : `${paths.spriteDir}/*.+(jpg|jpeg|png)`,
sprites : `${paths.spriteDir}/**/*.+(jpg|jpeg|png)`,
sass : `${paths.sassDir}/**/*.scss`,
js : `${paths.jsSrcDir}/**/*.+(js|vue)`,
entry : `${paths.jsSrcDir}/**/entry.js`
}
//CSS対応ブラウザのバージョン
export const browsers = [
'> 5% in JP',
'last 2 versions',
'ie >= 11',
'Android >= 4',
'iOS >= 8'
]
const config = { paths, globs, browsers }
export default config
これを作っておけば、新しいプロジェクトを作るときにgulpfile.babel.js
をコピーしてきて、こちらのファイルをちょいちょいっと書き換えるだけですぐに環境が整います。globs
やpaths
は自由に追加・変更できますので新しいgulpタスクを作った場合にもすぐ対応できます。
gulpタスクの詳細
次にタスクの中身です。
自動でブラウザリロードできるBrowsersync
や画像・svgの圧縮
などタスクを切り分けていろいろ作っていますが、
今回はCSSとJSのみをメモしておきます。
また機会があれば画像圧縮のタスクは使えるので紹介したいと思います。
① CSSビルド(gulpfile.babel.js/tasks/css.js)
import gulp from 'gulp'
import sass from 'gulp-sass'
import nodesass from 'node-sass'
sass.compiler = nodesass;
//エラーでgulpが終了するのを止める
import plumber from 'gulp-plumber'
//デスクトップ通知
import notify from 'gulp-notify'
//小さい画像をbase64に変換
import base64 from 'gulp-base64'
//PostCss
import postcss from 'gulp-postcss'
import cssnext from 'postcss-cssnext'
import cssImport from 'postcss-import'
//flexboxのバグを自動修正
import flexBugsFixes from 'postcss-flexbugs-fixes'
//ファイル名から画像パスやサイズを取得
import assets from 'postcss-assets'
//メディアクエリを整理する
import mqpacker from 'css-mqpacker'
//cssを圧縮する
import csso from 'gulp-csso'
//config
import {paths, globs, browsers} from '../config'
//cache
import diff from 'gulp-diff-build'
import cache from 'gulp-cached'
import progeny from 'gulp-progeny'
import browserSync from 'browser-sync'
//@importのglobを有効にする
import sassGlob from 'gulp-sass-glob'
//ファイル削除
import del from 'del'
//出力済みファイルを削除
function deleteCssDir(done) {
return del([paths.cssDir], done);
}
exports.deleteCssDir = deleteCssDir;
const processors = [
assets({
baseUrl : `${paths.serverDir}/`,
basePath : paths.themeDir,
loadPaths : [
'assets/images/',
'assets/svg/',
],
relative : true,
cachebuster : true,
}),
cssnext({
browsers,
features : {
autoprefixer : {
grid: true
}
}
}),
mqpacker({
sort: true
}),
flexBugsFixes,
cssImport({
path: [ 'node_modules' ]
})
];
function buildCss() {
return gulp.src(globs.sass, {
allowEmpty : true,
sourcemaps : true
})
.pipe(plumber({
errorHandler: notify.onError('<%= error.message %>')
}))
.pipe(sassGlob())
.pipe(diff())
.pipe(cache('sass'))
.pipe(progeny())
.pipe(sass({
outputStyle: 'expanded',
}))
.pipe(base64({
baseDir : paths.imageDir,
extensions : ['svg', 'png', /\.jpg#datauri$/i],
exclude : [/\.server\.(com|net)\/dynamic\//, '--live.jpg'],
maxImageSize : 8 * 1024,
debug : true
}))
.pipe(postcss(processors))
.pipe(csso({
restructure : false,
sourceMap : false,
debug : true
}))
.pipe(gulp.dest(paths.cssDir, {
sourcemaps : '.'
}))
.pipe(notify('buildCss finished'))
.pipe(browserSync.reload({
stream: true
}));
}
exports.buildCss = buildCss;
【2020.07.28】非推奨になったgulp.task()
のままになっていたのでタスクを新しい書き方に更新しました。
長年ちまちま更新してきたタスクなのでちょっと長いですね・・・笑
人によっては必要ない機能もあるかもしれませんが、30ファイルほどのSassをコンパイルしても1回目で0.6秒程度、2回目はキャッシュで早くなるので0.3秒程度となり、まぁ許容範囲だと思います。
モジュールに関しては結構たくさんあるのでさすがにひとつずつは説明できませんので、これは必須!というものだけピックアップしておきます。
gulp-postcss
こちらは生成するCSSを最適化・カスタマイズできるPostCSS
が使えるプラグイン。
色々と便利なオプションが設定できますが、有名どころではcssnext
のAutoprefixer
でしょうか。
僕はcss-mqpacker
というメディアクエリを整理するプラグインを使いたくて使い始めたのですが、いろんなカスタマイズができることを知り手放せなくなりました。
gulp-cached + gulp-progeny
こちらはセットで使うのが普通かなと思いますのでまとめてご紹介。gulp-cached
は文字通りキャッシュしてくれるので差分のみがビルドされます。gulp-progeny
はSassで@import
などを使用している場合にその依存関係を解決してコンパイルしてくれます。
詳しくはこちらの記事をどうぞ。
gulpでCSSの差分ビルド
https://qiita.com/73cha/items/270e2dc33c63292dd184
gulp-csso
こちらはCSSの圧縮プラグイン。
ファイルの軽量化には必須ですね。
他にも便利なプラグインを使っていますが、なくてもなんとかなるものばかりなので割愛させていただきます。プラグインの名前で検索したらすぐ出てくるものばかりです。
② JSビルド(gulpfile.babel.js/tasks/js.js)
import gulp from 'gulp';
import {globs, paths} from '../config';
//エラーでgulpが終了するのを止める
import plumber from 'gulp-plumber';
//デスクトップ通知
import notify from 'gulp-notify';
import path from 'path';
import fs from 'fs';
import through from 'through2';
import vinyl from 'vinyl';
import diff from 'gulp-diff-build';
//import cache from 'gulp-cached';
//webpackでファイル結合時に名前変更
import named from 'vinyl-named';
import gulpif from 'gulp-if';
import webpack from 'webpack';
import webpackStream from 'webpack-stream';
import webpackConfig from '../webpack.config';
import browserSync from 'browser-sync';
//ファイル削除
import del from 'del'
//出力済みファイルを削除
function deleteJsDistDir(done) {
return del([paths.jsDistDir], done);
}
exports.deleteJsDistDir = deleteJsDistDir;
//処理中のファイル名を入れる
let proccessings = [];
//jsのエントリーポイントファイルかどうか
const isEntryFile = (file) => {
let isEf = true;
if(!isExistFile(file.path)){
isEf = false;
}
else {
isEf = path.basename(file.path) === paths.jsEntryFileName;
}
return isEf;
}
//ファイルの存在チェック
const isExistFile = (file) => {
try {
fs.statSync(file);
return true
} catch(err) {
if(err.code === 'ENOENT') return false
}
}
//バンドル実行中のファイルかどうか
const isProccessing = (filePath) => {
return (proccessings.indexOf(filePath) >= 0);
}
//bundleされたファイルのみを次の処理に通す
const passThroughBundled = () => {
proccessings = [];
return through.obj(function (file, enc, cb) {
if( file.isNull() ){
cb(null,file);
}
else {
const basename = path.basename(file.path);
const isBundled = basename.indexOf('bundle.js') !== -1;
if(isBundled){
this.push(file);
}
cb();
}
});
}
function buildJs() {
return gulp.src(globs.js, {
allowEmpty : true
})
.pipe(plumber({
errorHandler: notify.onError('<%= error.message %>')
}))
.pipe(diff())
.pipe(cache('js'))
.pipe(named((file) => {
return file.relative ? path.parse(file.relative).dir : 'code';
}))
.pipe(gulpif(isEntryFile, webpackStream(webpackConfig, webpack)))
.pipe(passThroughBundled())
.pipe(gulp.dest(paths.jsDistDir))
.pipe(notify('buildJs finished'))
.pipe(browserSync.reload({
stream: true
}));
}
exports.buildJs = buildJs;
function buildJsAll() {
return gulp.src(globs.entry, {
allowEmpty: true
})
.pipe(plumber({
errorHandler: notify.onError('<%= error.message %>')
}))
.pipe(named((file) => {
return file.relative ? path.parse(file.relative).dir : 'code';
}))
.pipe(gulpif(isEntryFile, webpackStream(webpackConfig, webpack)))
.pipe(gulp.dest(paths.jsDistDir))
.pipe(notify('build:js-all finished'))
.pipe(browserSync.reload({
stream: true
}));
}
exports.buildJsAll = buildJsAll;
こちらは基本的にはJSそのものは何も処理しません。することと言えば保存した時に差分のあった場合だけをwebpack
に流したり、glob
で指定するentryファイルの存在チェックをしたりというフィルター処理でgulpの無駄な実行時間を減らす処理を書いています。ファイル結合や圧縮などはすべてwebpack
に任せて処理を分けています。
ただし、タスクだけはbuildJs
とbuildJsAll
に分けています。
本番モードでgulp-diff-build
などの差分ビルドを通さずにすべてのJSを確実にバンドルしたい時はbuildJsAll
、開発モードで更新したファイルだけをwebpackに通したい時はbuildJs
、という使い方をしています。開発の時はいちいち全部のファイルを通されても時間かかって困るので極力タスクの実行時間は短くしておきたいのでこうしています。
ここでもいくつかモジュールを紹介しておきます。
gulp-diff-build
こちらはファイルを監視して変更があった場合のみ、ファイルをストリームに流します。つまり変更がある場合のみgulpタスクを実行するのでwatch
した時に保存するたびに連続でタスクが実行されてしまうのを防止します。
これはかなり重宝しています!快適!
gulp-if
gulp
のタスク処理で条件分岐したい場合にこちらを使います。webpack
にストリームを流す際に余計なファイルが含まれていないかチェックするのに使っています。
through2
これはgulp
に独自の処理を入れたい時に使います。
プラグインの組み合わせだけではどうにもならないけど、ごく簡単な処理をはさみたい時があるのでこちらを使っています。JSビルド処理の中ではpassThroughBundled
という独自の関数を作成し、webpack
を通した後にbundle.js
という名前の入ったファイルのみをストリームに流すようにしています。こちらで意図しない余計なファイルがビルドされてしまうのを避けています。
webpack-stream
こちらはgulp
とwebpack
を連携するためのプラグイン。webpack
は絶対必要なのでこれが無いと始まりません。
③Webpack
続いてwebpack
を見ていきます。
これも人によって書き方が分かれるところですが、僕は1ファイルでなく3ファイルで管理しています。
- webpack.common.js:開発・本番モード共通
- webpack.dev.js:開発モード(JSを圧縮しない)
- webpack.prod.js:本番モード(JSを圧縮)
webpack4
から開発モードと本番モードが出来たので、圧縮処理を省いたものを開発モード、圧縮処理を入れたものを本番モードにしています。
具体的には以下コードで見ていきます。
webpack.common.js
import webpack from 'webpack'
import EncodingPlugin from 'webpack-encoding-plugin'
import VueLoaderPlugin from 'vue-loader/lib/plugin'
import {paths} from './config.js'
module.exports = {
cache : true,
output : {
filename : '[name].bundle.js',
},
optimization: {
splitChunks: {
name : 'vendor',
chunks : 'initial',
}
},
plugins : [
new VueLoaderPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.AggressiveMergingPlugin(),
new EncodingPlugin({
encoding: 'utf-8'
}),
new webpack.ProvidePlugin({
$ : 'jquery',
jQuery : 'jquery',
objectFitImages : 'object-fit-images',
anime : ['animejs/lib/anime.es.js', 'default'],
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: [
/(node_modules|bower_components)/
],
use: [{
loader: 'babel-loader'
}]
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
js: 'babel-loader'
}
}
}
]
},
resolve: {
modules : ["node_modules"],
alias : {
'@js' : paths.jsSrcDir,
'vue$': 'vue/dist/vue.esm.js'
}
}
};
こちらは共通設定です。通常のJSと、Vue.js
を最近よく使うのでそれに対応したものです。Typescript
もそろそろやってかないとと思っていますが、まだ手が出せていません…
設定について少し見ていきます。
cache
true
に設定するとwebpack
のキャッシュを有効にします。
output
これはエントリーファイルの親ディレクトリが名前になるようにgulp
とwebpack
を使って調整しています。どういうことかというと、
js/
└── /common
├── entry.js => エントリーファイル ①②をインポート
├── main.js => モジュール化した処理①
└── utils.js => モジュール化した処理②
└── /reserve
├── entry.js => エントリーファイル ③④をインポート
├── main.js => モジュール化した処理③
└── utils.js => モジュール化した処理④
JSを設置する場合はこういうファイル構成にして使います。
この場合、common.bundle.js
とreserve.bundle.js
という名前のファイルがビルドされるということです。
optimization.splitChunks
webpack4
で追加された機能。以前はCommonsChunkPlugin
というものがあったらしいですが使っていませんでした。こちら最近かなり重宝しています!
具体的に何ができるかというと、複数ファイルにまたがって使われている共通モジュールをバンドルして別ファイルとして出力する、ということができます。
先ほどの例で言うと、
optimization: {
splitChunks: {
name : 'vendor',
chunks : 'initial',
}
},
こういう設定がしてある場合、common.bundle.js
とreserve.bundle.js
というファイルの他にvendor.bundle.js
という共通ファイルが出来上がります。読み込む時は以下のようになります。
<script type='text/javascript' src='vendor.bundle.js'></script>
<script type='text/javascript' src='common.bundle.js'></script>
これの何が良いかというと3点あります。
1点目は、webpackの処理が早くなること。jQuery
やVue.js
などの大きいライブラリなどを共通ファイルとして出力してくれるのですが、そういったファイルは基本読み込むだけなので、保存するたびに書き換えることはまずないでしょう。そのためsplitChunks
を使って一旦作成されたvendor.bundle.js
のような共通モジュールはキャッシュが有効になり、変更されたファイルだけがビルドされるようになるのでビルド処理が格段に早くなります。けっこう大きいアプリケーションの開発などをしている時はwebpack
のビルドが遅いと開発にならなくなってきますのでこれだけでもかなり助かります。
続いて2点目。ファイルサイズが小さくなること。これは処理を共通化することで生まれるメリットです。ここで言えばcommon.bundle.js
もreserve.bundle.js
もvendor.bundle.js
を利用するので二重になっていた部分を削減できます。
最後に3点目。読み込む時にキャッシュが効く。
どのページでもvendor.bundle.js
を読み込むことになるので、ページごとにJSの内容を変える場合などでも共通化されていない部分だけを読み込めばいいので読み込み速度も早くなります。
plugins
ここには外部プラグインやwebpack
にある機能などを追加できます。
- VueLoaderPlugin:vue.js用
- webpack.optimize.OccurrenceOrderPlugin:ファイルサイズを縮小
- webpack.optimize.AggressiveMergingPlugin:コードを圧縮
- EncodingPlugin:ファイル形式を指定
- webpack.ProvidePlugin:あらかじめ読み込むモジュールを指定
module
ここではloaderの設定を書きます。babel-loader
でES6対応、vue-loader
で.vue拡張子のファイルに対応します。
resolve
alias
にパスを指定しておくと読み込みが楽になります。paths.jsSrcDir
がわかりにくいのでちょっと置き換えます。
resolve: {
modules : ["node_modules"],
alias : {
'@js' : path.join(__dirname, '../assets/js'),
'vue$': 'vue/dist/vue.esm.js'
}
}
設定しておくとJSファイル内でimport '../assets/js/common/main.js'
みたいに書いているものをimport '@js/common/main.js'
というようにファイルの相対位置などを気にせずに呼び出すことができるようになります。
webpack.dev.js
こちらは開発モードの設定ファイルです。
import { merge } from 'webpack-merge'
import common from './webpack.common.js'
module.exports = merge(common, {
mode : 'development',
devtool : 'cheap-module-eval-source-map',
});
webpack-merge
というプラグインを使ってwebpack.common.js
と設定をマージします。ここではソースマップだけ設定しておきます。
webpack.prod.js
こちらは本番モードの設定ファイルです。
import { merge } from 'webpack-merge'
import common from './webpack.common.js'
import TerserPlugin from 'terser-webpack-plugin'
module.exports = merge(common, {
mode : 'production',
optimization : {
minimizer : [
new TerserPlugin({
terserOptions: {
compress: {drop_console: true}
}
})
],
}
});
開発モードとの変更点は以下です。
・ソースマップを出力しない
・JSを圧縮する
JSの圧縮はけっこう時間がかかりますし、Chrome DevToolsツールなどからソースを見る時にわかりにくくなるので、開発モードでは使用しない方が良いです。
最後に
僕が個人的に使っている環境なのでかなり偏ったものになっているかもしれません。このままコピペで他のプロジェクトに使うことはできないと思います。ただ全体ではなく部分でもだれかの参考になればと思います。
今回はCSSとJSのビルドタスクだけを紹介しましたが、htmlの圧縮や画像圧縮など細々したタスクがたくさん増えて複雑化してきました。
今後、TypeScript
を使うとなった時にはもっとシンプル構成で新しい環境にしたいなぁ〜。
RELATED
NEW POSTS
【WordPress】GA4連携の人気記事ランキング機能を自作プラグイン化してみた
【netlify】ビルドイメージを更新 [ Ubuntu Xenial 16.04 → Ubuntu Focal 20.04 ]
【PHP】Google Business Profile APIを使ってクチコミを取得する
スクリーンショットのAPI「screendot」を使ってみた
【window.matchMedia】メディアクエリでhoverが使えるデバイスを判定
lax.jsの使い方【スクロール連動アニメーションの実装】