ããã«ã¡ã¯ãHabrïŒ
ææ°ã®åãã©ãŠã¶ãŒã§ã¯ã
ES6ã¢ãžã¥ãŒã«ã䜿çšã§ããããã«ãªããŸããã
äžèŠãããã¯å®å
šã«åœ¹ã«ç«ããªãããã§ã-çµå±ã®ãšãããç§ãã¡ã¯ãã¹ãŠãã€ã³ããŒããå
éšã®èª²é¡ã«çœ®ãæããã³ã¬ã¯ã¿ãŒã䜿çšããŠããŸãã ãããã仿§ãæãäžãããšããããã®ãããã§ãææ°ã®ãã©ãŠã¶ãŒçšã«å¥ã®ã¢ã»ã³ããªãæäŸã§ããããšãããããŸãã
ç«ã®äžã«ã¯ãå€ããã©ãŠã¶ãšç§ã®ç¥çµãæãªãããšãªããã¢ããªã±ãŒã·ã§ã³ã®ãµã€ãºã11ïŒ
åæžã§ãããšãã話ããããŸãã
ES6ã¢ãžã¥ãŒã«ã®æ©èœ
ES6ã¢ãžã¥ãŒã«ã¯ãåºãç¥ããåºã䜿çšãããŠããã¢ãžã¥ã©ãŒã·ã¹ãã ã§ãã
import { someFunc } from 'path/to/helpers.js'
export function someFunc() { }
ãã©ãŠã¶ã§ãã®ã¢ãžã¥ã©ãŒã·ã¹ãã ã䜿çšããã«ã¯ãåã¹ã¯ãªããã¿ã°ã«ã¢ãžã¥ãŒã«ã¿ã€ãã远å ããå¿
èŠããããŸãã å€ããã©ãŠã¶ã§ã¯ãã¿ã€ããtext / javascriptãšç°ãªãããšããããããã¡ã€ã«ãJavaScriptãšããŠå®è¡ããŸããã
<script type="module" src="/path/to/someFile.js"></script>
仿§ã«ã¯ãã¹ã¯ãªããã¿ã°ã®nomodule屿§ããããŸãã
ES6ã¢ãžã¥ãŒã«ããµããŒããããã©ãŠã¶ãŒã¯ãã®ã¹ã¯ãªãããç¡èŠããå€ããã©ãŠã¶ãŒã¯ãããããŠã³ããŒãããŠå®è¡ããŸãã
<script nomodule src="/path/to/someFileFallback.js"></script>
ç°¡åã«2ã€ã®ã¢ã»ã³ããªãäœæã§ããããšãããããŸãã1ã€ã¯ææ°ã®ãã©ãŠã¶ãŒçšã®ã¢ãžã¥ãŒã«ã¿ã€ãïŒModern BuildïŒããã1ã€ã¯å€ããã©ãŠã¶ãŒçšã®nomoduleïŒãã©ãŒã«ããã¯ãã«ãïŒã§ãã
<script type="module" src="/path/to/someFile.js"></script> <script nomodule src="/path/to/someFileFallback.js"></script>
ãªããããå¿
èŠã§ãã
ãããžã§ã¯ããæ¬çªã«éä¿¡ããåã«ã次ã®ããšãè¡ãå¿
èŠããããŸãã
- ããªãã£ã«ã远å ããŸãã
- ææ°ã®ã³ãŒããå€ãã³ãŒãã«çœ®ãæããŸãã
ç§ã®ãããžã§ã¯ãã§ã¯ããã©ãŠã¶ã®æå€§æ°ãå Žåã«ãã£ãŠã¯
IE 10ããµããŒãããããšããŠããŸãã ãããã£ãŠãããªãã¡ã€ã«ã®ãªã¹ãã¯ães6.promiseães6.object.valuesãªã©ã®åºæ¬çãªãã®ã§æ§æãããŠããŸãã ãã ãã
ES6ã¢ãžã¥ãŒã«ãæèŒãããã©ãŠã¶ãŒã¯ãã¹ãŠã®ES6ã¡ãœããããµããŒãããŠãããäœåãªãããã€ãã®ããªãã£ã«ã¯å¿
èŠãããŸããã
ãŸãããã©ã³ã¹ãã€ã¬ãŒã·ã§ã³ã«ããããã¡ã€ã«ãµã€ãºã«é¡èãªããŒã¯ãæ®ããŸããbabel/ preset-envã¯ã25åã®ãã©ã³ã¹ãã©ãŒããŒã䜿çšããŠã»ãšãã©ã®ãã©ãŠã¶ãŒãã«ããŒããŸãããããããã³ãŒãã®ãµã€ãºã倧ããããŸãã åæã«ã
ES6ã¢ãžã¥ãŒã«ããµããŒããããã©ãŠã¶ãŒã®å Žåããã©ã³ã¹ãã©ãŒããŒã®æ°ã¯9ã«åæžãããŸãã
ãã®ãããææ°ã®ãã©ãŠã¶ãŒã®ã¢ã»ã³ããªã§ã¯ãäžèŠãªããªãã¡ã€ã«ãåé€ããŠãã©ã³ã¹ãã©ãŒããŒã®æ°ãæžããããšãã§ããŸããããã«ãããçµæã®ãã¡ã€ã«ã®ãµã€ãºã«å€§ããªåœ±é¿ãåºãŸãã
ããªãã¡ã€ã«ã远å ããæ¹æ³
ææ°ã®ãã©ãŠã¶åãã«Modern Buildãæºåããåã«ããããžã§ã¯ãã«ããªãã£ã«ã远å ããæ¹æ³ã«ã€ããŠèšåãã䟡å€ããããŸãã
éåžžããããžã§ã¯ãã¯core-jsã䜿çšããŠãå¯èœãªãã¹ãŠã®ããªãã£ã«ã远å ããŸãã
ãã¡ããããã®ã©ã€ãã©ãªã®88Kãã€ãã®ããªãã¡ã€ã«ãã¹ãŠãå¿
èŠãªããã§ã¯ãªãããã©ãŠã¶ãªã¹ãã«å¿
èŠãªãã®ã ããå¿
èŠã§ãã ãã®æ©èœã¯ãbabel / preset-envããã³ãã®useBuiltInsãªãã·ã§ã³ã䜿çšããŠäœ¿çšã§ããŸãã ãšã³ããªã«èšå®ãããšãcore-jsã®ã€ã³ããŒãã¯ããã©ãŠã¶ã«å¿
èŠãªåã
ã®ã¢ãžã¥ãŒã«ã®ã€ã³ããŒãã«çœ®ãæããããŸãã
module.exports = { presets: [ ['@babel/preset-env', { useBuiltIns: 'entry', }] ], };
import 'core-js';
import "core-js/modules/es6.array.copy-within"; import "core-js/modules/es6.array.fill"; import "core-js/modules/es6.array.find";
ãããããã®ãããªå€æã«ãããäžèŠãªéåžžã«å€ãå€é¡ã®äžéšã®ã¿ãåãé€ããŸããã TypedArrayãWeakMapãããã³ãããžã§ã¯ãã§æ±ºããŠäœ¿çšãããªãä»ã®å¥åŠãªãã®ã®ããã®å€çžæ§ããŸã ãããŸãã
ãã®åé¡ãå®å
šã«å
æããã«ã¯ãuseBuiltInsãªãã·ã§ã³ã®å€ãusageã«èšå®ããŸãã ã³ã³ãã€ã«ã®æ®µéã§ãbabel / preset-envã¯ãéžæãããã©ãŠã¶ãŒã§äœ¿çšã§ããªãæ©èœã䜿çšããããã«ãã¡ã€ã«ãåæãããããã«ããªãã¡ã€ã«ã远å ããŸãã
module.exports = { presets: [ ['@babel/preset-env', { useBuiltIns: 'usage', }] ], };
function sortStrings(strings) { return strings.sort(); } function createResolvedPromise() { return Promise.resolve(); }
import "core-js/modules/es6.array.sort"; import "core-js/modules/es6.promise"; function sortStrings(strings) { return strings.sort(); } function createResolvedPromise() { return Promise.resolve(); }
äžèšã®äŸã§ã¯ãbabel / preset-envããœãŒã颿°ã«èŠªåã远å ããŸããã JavaScriptã§é¢æ°ã«æž¡ããããªããžã§ã¯ãã®ã¿ã€ããèŠã€ããããšã¯ã§ããŸãããããã¯ããœãŒã颿°ãå«ãé
åãŸãã¯ã¯ã©ã¹ãªããžã§ã¯ãã«ãªããŸãããbabel / preset-envã¯ææªã®ã·ããªãªãéžæããããªãã¡ã€ã«ãæ¿å
¥ããŸãã
babel / preset-envãééã£ãŠããç¶æ³ã¯åžžã«èµ·ãããŸãã äžèŠãªpolyphilesãåé€ããã«ã¯ãexcludeãªãã·ã§ã³ã䜿çšããŠãäœåãªpolyphilesãã€ã³ããŒãããã³åé€ããŸãã
module.exports = { presets: [ ['@babel/preset-env', { useBuiltIns: 'usage',
ç§ã¯fast-asyncã䜿çšããŠããã®ã§ãregenerator-runtimeã¢ãžã¥ãŒã«ãèæ
®ããŸããïŒ ãããŠãç§ã¯çã«å©èšããŸã ïŒãã¢ãã³ãã«ããäœæãã
Modern Buildãã»ããã¢ããããŸãããã
ãããžã§ã¯ãã«ãå¿
èŠãªãã¹ãŠã®ãã©ãŠã¶ãŒã説æããbrowserslistãã¡ã€ã«ãããããšã確èªããŸãã
/* .browserslistrc */ > 0.5% IE 10
ãã«ãäžã«BROWSERS_ENVç°å¢å€æ°ã远å ããŸããããã¯ããã©ãŒã«ããã¯ïŒãã©ãŒã«ããã¯ãã«ãã®å ŽåïŒããã³ã¢ãã³ïŒã¢ãã³ãã«ãã®å ŽåïŒã®å€ãåãããšãã§ããŸãã
/* package.json */ { "scripts": { /* ... */ "build": "NODE_ENV=production webpack /.../", "build:fallback": "BROWSERS_ENV=fallback npm run build", "build:modern": "BROWSERS_ENV=modern npm run build" }, /* ... */ }
次ã«babel / preset-envã®æ§æã倿ŽããŸãã ããªã»ããã§ãµããŒããããŠãããã©ãŠã¶ãæå®ããã«ã¯ããªãã·ã§ã³ã®ã¿ãŒã²ããããããŸãã 圌女ã«ã¯ç¹å¥ãªç¥èª-esmodulesããããŸãã ããã䜿çšããå Žåãbabel / preset-envã¯
ES6ã¢ãžã¥ãŒã«ããµããŒããããã©ãŠã¶ãèªåçã«çœ®ãæã
ãŸã ã
const isModern = process.env.BROWSERS_ENV === 'modern'; module.exports = { presets: [ ['@babel/preset-env', { useBuiltIns: 'usage',
Babel / preset-envã¯ããã¹ãŠã®äœæ¥ãããã«è¡ããŸããå¿
èŠãªããªãã£ãŒã«ãšå€æã®ã¿ãéžæããŸãã
ããã§ãã³ã³ãœãŒã«ããã³ãã³ããå®è¡ããã ãã§ãææ°ãŸãã¯å€ããã©ãŠã¶çšã®ãããžã§ã¯ããæ§ç¯ã§ããŸãïŒ
ãã€ã³ãã¢ãã³ãšãã©ãŒã«ããã¯ãã«ã
æåŸã®ã¹ãããã¯ãã¢ãã³ãã«ããšãã©ãŒã«ããã¯ãã«ãã1ã€ã«ãŸãšããããšã§ãã
ãã®ãããªãããžã§ã¯ãæ§é ãäœæããäºå®ã§ãã
index.htmlã«ã¯ãäž¡æ¹ã®ã¢ã»ã³ããªããã®å¿
èŠãªjavascriptãã¡ã€ã«ãžã®ãªã³ã¯ããããŸãã
/* index.html */ <html> <head> </head> <body> <script type="module" src="/modern/js/app.540601d23b6d03413d5b.js"></script> <script nomodule src="/fallback/js/app.4d03e1af64f68111703e.js"></script> </body> </html>
ãã®æé ã¯3ã€ã®éšåã«åããããšãã§ããŸãã
- ç°ãªããã£ã¬ã¯ããªã§ã¢ãã³ãã«ããšãã©ãŒã«ããã¯ãã«ãããã«ãããŸãã
- å¿
èŠãªjavascriptãã¡ã€ã«ãžã®ãã¹ã«é¢ããæ
å ±ãååŸããŸãã
- ãã¹ãŠã®javascriptãã¡ã€ã«ãžã®ãªã³ã¯ãå«ãindex.htmlãäœæããŸãã
ããå§ããŸãããïŒ
å¥ã®ãã£ã¬ã¯ããªã§ã¢ãã³ãã«ããšãã©ãŒã«ããã¯ãã«ãããã«ããã
æåã«ãæãç°¡åãªæé ãå®è¡ããŸããããdistãã£ã¬ã¯ããªå
ã®ç°ãªããã£ã¬ã¯ããªã«ModernãšFallback BuildãåéããŸãã
output.pathã«ç®çã®ãã£ã¬ã¯ããªãæå®ããããšã¯ãåã«äžå¯èœã§ããwebpackã«ã¯ãdistãã£ã¬ã¯ããªã«é¢é£ãããã¡ã€ã«ãžã®ãã¹ãå¿
èŠã§ããããã§ãïŒindex.htmlã¯ãã®ãã£ã¬ã¯ããªã«ãããä»ã®ãã¹ãŠã®äŸåé¢ä¿ã¯ããã®ãã£ã¬ã¯ããªã«é¢é£ä»ããããŸãïŒã
ãã¡ã€ã«ãã¹ãçæããããã®ç¹å¥ãªé¢æ°ãäœæããŸãã
const path = require('path'); const isModern = process.env.BROWSERS_ENV === 'modern'; const prefix = isModern ? 'modern' : 'fallback'; module.exports = relativePath => ( path.join(prefix, relativePath) );
const getFilePath = require('path/to/getFilePath'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { mode: 'production', output: { path: 'dist', filename: getFilePath('js/[name].[contenthash].js'), }, plugins: [ new MiniCssExtractPlugin({ filename: getFilePath('css/[name].[contenthash].css'), }), ], }
ãã®ãããžã§ã¯ãã¯ãModern BuildãšFallback Buildã®ç°ãªããã£ã¬ã¯ããªã«éãŸãå§ããŸããã
å¿
èŠãªjavascriptãã¡ã€ã«ãžã®ãã¹ã«é¢ããæ
å ±ãååŸãã
åéããããã¡ã€ã«ã«é¢ããæ
å ±ãååŸããã«ã¯ãwebpack-manifest-pluginãæ¥ç¶ããŸãã ãã«ãã®æåŸã«ããã¡ã€ã«ãžã®ãã¹ã«é¢ããããŒã¿ãå«ãmanifest.jsonãã¡ã€ã«ã远å ããŸãã
const getFilePath = require('path/to/getFilePath'); const WebpackManifestPlugin = require('webpack-manifest-plugin'); module.exports = { mode: 'production', plugins: [ new WebpackManifestPlugin({ fileName: getFilePath('manifest.json'), }), ], }
ããã§ãåéããããã¡ã€ã«ã«é¢ããæ
å ±ãåŸãããŸããã
{ "app.js": "/fallback/js/app.4d03e1af64f68111703e.js", }
ãã¹ãŠã®javascriptãã¡ã€ã«ãžã®ãªã³ã¯ãå«ãindex.htmlãäœæãã
æ®ã£ãŠããã®ã¯ãindex.htmlã远å ããå¿
èŠãªãã¡ã€ã«ãžã®ãã¹ãæ¿å
¥ããããšã ãã§ãã
htmlãã¡ã€ã«ãçæããã«ã¯ãModern Buildäžã«html-webpack-pluginã䜿çšããŸãã html-webpack-pluginã¯ææ°ã®ãã¡ã€ã«èªäœãžã®ãã¹ãæ¿å
¥ããåã®æé ã§äœæãããã¡ã€ã«ãããã©ãŒã«ããã¯ãã¡ã€ã«ãžã®ãã¹ãååŸããå°ããªwebpackãã©ã°ã€ã³ã䜿çšããŠHTMLã«è²Œãä»ããŸãã
const HtmlWebpackPlugin = require('html-webpack-plugin'); const ModernBuildPlugin = require('path/to/ModernBuildPlugin'); module.exports = { mode: 'production', plugins: [ ...(isModern ? [
package.jsonãæŽæ°ããŸãã
/* package.json */ { "scripts": { /* ... */ "build:full": "npm run build:fallback && npm run build:modern" }, /* ... */ }
npm run buildïŒfullã³ãã³ãã䜿çšããŠãModern BuildãšFallback Buildã§1ã€ã®htmlãã¡ã€ã«ãäœæããŸãã ããã§ããã©ãŠã¶ã¯å®è¡å¯èœãªJavaScriptãåãåããŸãã
ã¢ããªã±ãŒã·ã§ã³ã«ã¢ãã³ãã«ãã远å ãã
ç§ã®ãœãªã¥ãŒã·ã§ã³ãçŸå®ã®ãã®ã§ãã¹ãããããã«ãç§ã¯ãããèªåã®ãããžã§ã¯ãã®äžã€ã«å
¥ããŸããã æ§æã®ã»ããã¢ããã«ã¯1æéããããããJavaScriptãã¡ã€ã«ã®ãµã€ãºã¯11ïŒ
æžå°ããŸããã ã·ã³ãã«ãªå®è£
ã§çŽ æŽãããçµæã
æåŸãŸã§èšäºãèªãã§ãããŠããããšãïŒ
äœ¿çšææ