tag:crieit.net,2005:https://crieit.net/tags/terser-webpack-plugin/feed 「terser-webpack-plugin」の記事 - Crieit Crieitでタグ「terser-webpack-plugin」に投稿された最近の記事 2020-11-24T23:34:09+09:00 https://crieit.net/tags/terser-webpack-plugin/feed tag:crieit.net,2005:PublicArticle/16236 2020-11-24T23:34:09+09:00 2020-11-24T23:34:09+09:00 https://crieit.net/posts/gulp4-webpack5-terser-webpack-plugin-error-resolutions-20201124 続・ Gulp 4 + Webpack 5 を試す (resolutions 使用) <p>以前、<a href="https://crieit.net/posts/gulp4-webpack5-terser-webpack-plugin-error-20201020">Gulp 4 + Webpack 5 を試す ( 未完 / terser-webpack-plugin で TypeError: Cannot read property ‘javascript’ of undefined エラーになる)</a>の記事で Gulp 4 + Webpack 5 の実験をしましたが、その続きです。</p> <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p><a href="https://crieit.net/posts/backstopjs-test-20201122">BackstopJS を試す (Error: Failed to launch the browser process! エラー発生→ puppeteer のバージョンを指定して解決)</a>で <code>package.json</code> に <code>resolutions</code> を記述して Yarn で内部依存パッケージのバージョンを強制的に変更する手法を取りましたが、同様の手法が使えるのではないか、と思った次第です。</p> <h2 id="検証"><a href="#%E6%A4%9C%E8%A8%BC">検証</a></h2> <h3 id="package.json"><a href="#package.json">package.json</a></h3> <p>```json:package.json<br /> // 略<br /> "devDependencies": {<br /> // 略<br /> "webpack": "^5.6.0",<br /> "webpack-stream": "^6.1.1",<br /> "terser-webpack-plugin": "^5.0.3",<br /> // 略<br /> },<br /> "resolutions": {<br /> "webpack": "^5.6.0"<br /> },<br /> // 略</p> <pre><code><br />上述のように `resolutions` で Webpack のバージョンを指定。 ### gulp/tasks/js.js `gulp/tasks/js.js` は前回のまま。 ### webpack.config.js `webpack.config.js` は source map のための設定を追加した以外はそのままです。 ```javascript:webpack.config.js const _ = require('./gulp/plugin'); const dir = require('./gulp/dir'); const mode = () => { return process.env.DEV_MODE === 'dev' ? 'development' : 'production'; }; const modeFlag = () => { return process.env.DEV_MODE === 'dev' ? false : true; }; const entry = () => { const entries = _.glob .sync( '**/*.js', { ignore: [ '_plugins/**' ], cwd: dir.src.js } ) .map(function (key) { return [key, _.path.resolve(dir.src.js, key)]; }); return Object.fromEntries(entries) }; const configs = { mode: mode(), entry: entry(), output: { filename: '[name]' }, optimization: { minimizer: [ new _.webpackTerser({ extractComments: 'some', terserOptions: { compress: { drop_console: modeFlag(), }, }, }), ], } }; if (process.env.DEV_MODE === 'dev') { // 追加 configs.devtool = 'inline-source-map'; } module.exports = configs; </code></pre> <p>これで <code>yarn restart</code> などすると</p> <pre><code class="bash">$ gulp # 略 [hh:ii:ss] asset app.js 226 KiB [emitted] [minimized] (name: app.js) 1 related asset webpack 5.6.0 compiled successfully [hh:ii:ss] Finished 'jsBuild' after 20 s </code></pre> <p>動きました!</p> <hr /> <p>後々は <code>resolutions</code> なしでも動くようにしたいですが、ひとまず動く形になったのでメモしておきます。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="Yarn の reasolutions"><a href="#Yarn+%E3%81%AE+reasolutions">Yarn の reasolutions</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://nju33.com/yarn/resolutions%20%E3%81%A7%E4%BE%9D%E5%AD%98%E3%81%AE%E4%BE%9D%E5%AD%98%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B">yarn: resolutions で依存の依存のバージョンを指定する - nju33</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/16235 2020-11-24T23:28:18+09:00 2022-02-25T22:47:24+09:00 https://crieit.net/posts/gulp4-webpack5-terser-webpack-plugin-error-20201020 Gulp 4 + Webpack 5 を試す ( 未完 / terser-webpack-plugin で TypeError: Cannot read property 'javascript' of undefined エラーになる) <p>以前、<a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2020/10/06/browserify-babelify-gulp-transpile-ie/">browserify + babelify + Gulp で IE11対応を試す</a>の記事で browserify + babelify を試しましたが、今回は Webpack に挑んでみます。</p> <p>ただし、プレーンな Gulp 環境ではなく、 <a target="_blank" rel="nofollow noopener" href="https://github.com/arm-band/kiribi_ususama/tree/8a06ef719725236c26337a71bb2b1f9b64ef0900">Ususama</a> で。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <h3 id="package.json"><a href="#package.json">package.json</a></h3> <pre><code class="json">// 略 "devDependencies": { // 略 "glob": "7.1.6", "webpack": "^5.1.3", "webpack-stream": "^6.1.0", "terser-webpack-plugin": "^5.0.0", // 略 } // 略 </code></pre> <p><code>gulp-uglify-es</code> と <code>gulp-concat</code> を除き、代わりに <code>webpack</code> 本体と Gulp で Webpack を使用するために必要な <code>webpack-stream</code> 、そして minifier の terser の Webpack 用プラグインである <code>terser-webpack-plugin</code> を追加。</p> <h3 id="gulp/tasks/js.js"><a href="#gulp%2Ftasks%2Fjs.js">gulp/tasks/js.js</a></h3> <pre><code class="javascript">const gulp = require('gulp'); const plumber = require('gulp-plumber'); const notify = require('gulp-notify'); const webpack = require('webpack'); const webpackStream = require('webpack-stream'); const rename = require('gulp-rename'); const dir = { dist: { js: './dist/js' } }; const webpackConfig = require('../../weppack.config'); const jsBuild = () => { return _.webpackStream(webpackConfig) .pipe(_.plumber({ errorHandler: _.notify.onError({ message: 'Error: <%= error.message %>', title: 'jsLibBuild' }) })) .pipe(_.rename((path) => { path.basename += '.min' path.extname = '.js' })) .pipe(_.gulp.dest(dir.dist.js)); }; module.exports = jsBuild; </code></pre> <h3 id="webpack.config.js"><a href="#webpack.config.js">webpack.config.js</a></h3> <pre><code class="javascript">const webpack = require('webpack'); const webpackTerser = require('terser-webpack-plugin'); const path = require('path'); const glob = require('glob'); const dotenv = require('dotenv').config(); const dir = { src: { js: './src/js' } }; const mode = () => { return process.env.DEV_MODE === 'dev' ? 'development' : 'production'; }; const modeFlag = () => { return process.env.DEV_MODE === 'dev' ? false : true; }; const entry = () => { const entries = _.glob .sync( '**/*.js', { ignore: [ '_plugins/**' ], cwd: dir.src.js } ) .map(function (key) { return [key, _.path.resolve(dir.src.js, key)]; }); return Object.fromEntries(entries) }; module.exports = { mode: mode(), entry: entry(), output: { filename: '[name]' }, optimization: { minimizer: [ new _.webpackTerser({ extractComments: 'some', terserOptions: { compress: { drop_console: modeFlag(), }, }, }), ], } }; </code></pre> <p>いくつかの記事を参考にしながらタスクを組みます。</p> <p>自分でカスタマイズした部分は以下。</p> <ul> <li><code>.env</code> で <code>dev</code>, <code>demo</code>, <code>prod</code> のモードを切り替えているので、その部分を <code>process.env.DEV_MODE</code> で振り分け <ul> <li>Webpack の設定の <code>mode</code> と <code>terser-webpack-plugin</code> の <code>drop_console</code> のフラグが関係しています</li> </ul></li> <li>複数の <code>.js</code> ファイルをエントリポイントにしたかったのでその部分は<a target="_blank" rel="nofollow noopener" href="https://qiita.com/masato_makino/items/7130bbe408ca929e7f0d">webpackのentryファイルを複数指定、globパッケージの使い方 - Qiita</a>を参考に</li> <li>最終的なファイル名は <code>XXX.min.js</code> の形にしたかったので <code>gulp-rename</code> を通しました</li> </ul> <h2 id="jQuery の扱い"><a href="#jQuery+%E3%81%AE%E6%89%B1%E3%81%84">jQuery の扱い</a></h2> <p>タスク自体は上記のやり方で走ることが確認できました( <code>DEV_MODE=dev</code> )。</p> <p>次は現時点ではまだ jQuery を使用しているので、 jQuery をどう読み込ませるかが課題ですが、以下のようにして動作することを確認しました。</p> <h3 id="app.js"><a href="#app.js">app.js</a></h3> <pre><code class="javascript">import $ from 'jquery'; import 'jquery.easing/jquery.easing'; $(() => { /* 処理 */ }); </code></pre> <h3 id="sitesearch.js"><a href="#sitesearch.js">sitesearch.js</a></h3> <pre><code class="javascript">import $ from 'jquery'; import List from 'list.js'; //サイト内検索 export default () => { const options = { valueNames: ['searchTitle', 'searchText'], }; const searchList = new List('listSearch', options); //hits searchList.on('searchComplete', function (a) { $('#hits').text(a.matchingItems.length); }); }; </code></pre> <p>サイト内検索で <a target="_blank" rel="nofollow noopener" href="https://listjs.com">List.js</a> を使用しているのですが、これについては<a target="_blank" rel="nofollow noopener" href="https://github.com/javve/list.js/issues/559">How am I suppose to import list.js with es6 and webpack ? · Issue #559 · javve/list.js</a>の Issues の方法で解決しました。</p> <p>ここまでは比較的順調でした。</p> <p>しかし、間も無く壁に突き当たることになります……。</p> <h2 id="TypeError: Cannot read property 'javascript' of undefined エラー"><a href="#TypeError%3A+Cannot+read+property+%27javascript%27+of+undefined+%E3%82%A8%E3%83%A9%E3%83%BC">TypeError: Cannot read property 'javascript' of undefined エラー</a></h2> <p><code>DEV_MODE=dev</code> で動作することは確認できたので、 <code>DEV_MODE=prod</code> に切り替えました。</p> <p>すると、以下のエラーが出てしまいました。</p> <pre><code>TypeError: Cannot read property 'javascript' of undefined at PATH\TO\PROJECT\node_modules\terser-webpack-plugin\dist\index.js:366:38 </code></pre> <p><code>DEV_MODE=dev</code> に戻すと先ほどと同じように問題なく動作。上記でこのフラグが関係するのは <code>mode</code> と <code>terser-webpack-plugin</code> の <code>drop_console</code> の2箇所なので、そのどちらかだろうとアタリを付けます。</p> <p>試しに <code>drop_console</code> を常に <code>false</code> としましたが、 <code>DEV_MODE=prod</code> でエラーは再現しました。</p> <p>となると、 <code>mode</code> の方ということになります。</p> <p>ここでエラー文で検索すると、以下の Issues を発見。 <code>terser-webpack-plugin</code> 本家のリポジトリです。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/webpack-contrib/terser-webpack-plugin/issues/335">TypeError: Cannot read property 'javascript' of undefined ・ Issue #335 ・ webpack-contrib/terser-webpack-plugin</a></li> </ul> <p>発生個所も含めてエラー文が同じです。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/webpack-contrib/terser-webpack-plugin/issues/335#issuecomment-709997726">TypeError: Cannot read property 'javascript' of undefined · Issue #335 · webpack-contrib/terser-webpack-plugin</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/webpack-contrib/terser-webpack-plugin/issues/335#issuecomment-710004332">TypeError: Cannot read property 'javascript' of undefined ・ Issue #335 ・ webpack-contrib/terser-webpack-plugin</a></li> </ul> <p>別の方のコメントを見ると、原因は以下の模様。</p> <ul> <li>terser-webpack-plugin 5 は Webpack 4 とは互換性がない</li> <li><code>webpack-stream</code> の内部で使用している Webpack がバージョン 4 系</li> </ul> <blockquote> <p>yep, we are working on it, release with fix will be today/tomorrow</p> <p><a target="_blank" rel="nofollow noopener" href="https://github.com/webpack-contrib/terser-webpack-plugin/issues/335#issuecomment-710032380">TypeError: Cannot read property 'javascript' of undefined ・ Issue #335 ・ webpack-contrib/terser-webpack-plugin</a> (2020/10/16日 22:04 JST)</p> </blockquote> <p>わりとタイムリーなものを踏んでしまったようなので、 fixed されるのを待つ感じですかね……。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h2 id="Gulp + Webpack"><a href="#Gulp+%2B+Webpack">Gulp + Webpack</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/tonkotsuboy_com/items/2d4f3862e6d05dc0bea1">Gulpで始めるwebpack 4入門 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/am10/items/2516fa04def815195ffe">gulp + webpack + babelをつかってみた - Qiita</a></li> </ul> <h3 id="webpack-stream"><a href="#webpack-stream">webpack-stream</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/webpack-stream">webpack-stream - npm</a></li> </ul> <h2 id="Webpack, 複数エントリポイントとoutput"><a href="#Webpack%2C+%E8%A4%87%E6%95%B0%E3%82%A8%E3%83%B3%E3%83%88%E3%83%AA%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%81%A8output">Webpack, 複数エントリポイントとoutput</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/masato_makino/items/7130bbe408ca929e7f0d">webpackのentryファイルを複数指定、globパッケージの使い方 - Qiita</a></li> </ul> <h2 id="List.js import"><a href="#List.js+import">List.js import</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/javve/list.js/issues/559">How am I suppose to import list.js with es6 and webpack ? · Issue #559 · javve/list.js</a></li> </ul> <h2 id="terser-webpack-plugin"><a href="#terser-webpack-plugin">terser-webpack-plugin</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/webpack-contrib/terser-webpack-plugin/issues/335">TypeError: Cannot read property 'javascript' of undefined ・ Issue #335 ・ webpack-contrib/terser-webpack-plugin</a></li> </ul> arm-band