
倿°ã®èšäºïŒããšãã°ã ãã®èšäºïŒãèªãã åŸããæç«ãã¢ãããŒãã䜿çšããŠåçŽãªãµã€ããäœæãããšãã«ãNode.jsã䜿çšããææ°ã®ã¢ãããŒãã«åãæ¿ããããšã«ããŸããã 以äžã¯ã Webpack 4ã䜿çšããŠåçŽãªéçãµã€ããæ§ç¯ããè§£æäŸã§ãã åé¡ã解決ããããã®æç€ºãèŠã€ãããªãã£ãããããã®èšäºã¯æžãããŸããããã¹ãŠãæççã«åéããªããã°ãªããŸããã§ããã
åé¡ã®å£°æ
ãµã€ãã¯ãç¬èªã®CSSã¹ã¿ã€ã«ãšJavaScriptãã¡ã€ã«ãåããHTMLããŒãžã®åçŽãªã»ããã§ãã ãµã€ãããœãŒã¹ããçµã¿ç«ãŠããããžã§ã¯ããäœæããå¿
èŠããããŸãã
- SASSïŒããæ£ç¢ºã«ã¯SCSSïŒãã¡ã€ã«ããã1ã€ã®CSSãã¡ã€ã«ã圢æãããŸãã
- ããŸããŸãªJavaScriptã©ã€ãã©ãªãšãŠãŒã¶ãŒã³ãŒããã1ã€ã®JavaScriptãã¡ã€ã«ã圢æãããŸãã
- HTMLããŒãžã¯ãã³ãã¬ãŒããšã³ãžã³ã䜿çšããŠçµã¿ç«ãŠãããŸãããã³ãã¬ãŒããšã³ãžã³ã§ã¯ãããããŒãšããã¿ãŒã®ã³ã³ãã³ããåå¥ã®ãã¡ã€ã«ã«åå²ã§ããŸãã
çµã¿ç«ãŠããããµã€ãã§ã¯ãReactãVue.jsã䜿çšããªãã§ãã ããã
ãã¯ãããžãŒãéžæãããšããçŸæç¹ã§æã人æ°ã®ãããã®ãéžæãããŸãã ãã®ãããç§ã¯GruntãšGulpã®äž¡æ¹ãWebpackã«è³æããŠæåŠããŸããããæ£çŽãªãšãããå調ãã®ããã«Gulpæ§æããã奜ãã§ããã
ããšãã°ãBootstrap 4ã«åºã¥ãè€æ°ã®ããŒãžãã³ã³ãã€ã«ãããŸãããããã¯åãªãäŸã§ãã
Node.jsãã€ã³ã¹ããŒã«ãããŠãããšæ³å®ããïŒWindowsã§ã¯ãã€ã³ã¹ããŒã©ãŒã¯ãæ¬¡ãæ¬¡ãã®ã¹ã¿ã€ã«ã§ããŠã³ããŒãããã³ã€ã³ã¹ããŒã«ãããã ãã§ãïŒãã³ãã³ãã©ã€ã³ã§äœæ¥ã§ããŸãã
æŽæ°ãã 远å ã®èšå®ãªãã§ïŒGitHubããŒãžãªã©ã§ïŒãã¹ãã£ã³ã°ã«ã¢ããããŒãããããã³ã³ãã¥ãŒã¿ãŒã§ããŒã«ã«ã«éãããšãã§ããæ¢è£œã®HTMLããŒãžã®ã»ãããååŸããå¿
èŠããããŸãã
ãããžã§ã¯ãæ§é
ãããžã§ã¯ãã®äžè¬çãªæ§é ã¯æ¬¡ã®ãšããã§ãã
. âââ dist - , ââ⬠src - â âââ favicon - â âââ fonts - â ââ⬠html - HTML â â âââ includes - (header, footer) â â âââ views - HTML â âââ img - (, .) â âââ js - JavaScript â âââ scss - SSS â âââ uploads - (, .) âââ package.json - Node.js âââ webpack.config.js - Webpack
åãæ§é ã§ãããäŸã«ååšãããã¡ã€ã«ã衚瀺ããŠããŸãïŒ . âââ dist ââ⬠src â ââ⬠favicon â â âââ favicon.ico â ââ⬠fonts â â âââ Roboto-Regular.ttf â ââ⬠html â â ââ⬠includes â â â âââ footer.html â â â âââ header.html â â ââ⬠views â â âââ index.html â â âââ second.html â ââ⬠img â â âââ logo.svg â ââ⬠js â â âââ index.js â ââ⬠scss â â âââ style.scss â ââ⬠uploads â âââ test.jpg âââ package.json âââ webpack.config.js
ãã¡ãã³ã³ã®äžã§ãã©ã«ãå
šäœãéžæãããŸããããã¯ãææ°ã®Webã§ã¯1ã€ã®icoãã¡ã€ã«ã ãã§ã¯ã§ããªãããã§ãã ããããããšãã°ããã®åäžã®ãã¡ã€ã«ã®ã¿ã䜿çšãããŸãã
ç©è°ããããæ±ºå®ã¯ãç»åãimg
ãšuploads
2ã€ã®ãã©ã«ããŒã«åå²ããããã«èŠãããããããŸããã ããããããã§ã¯Wordpressã®ãã¡ã€ã«ã¬ã€ã¢ãŠãã®ã€ããªãã®ãŒã䜿çšããŸããã ç§ã®æèŠã§ã¯ããã¹ãŠã®ç»åã1ã€ã®ãã©ã«ããŒã«å
¥ããããšã¯ãå§ãã§ããŸããã
ãã®ãããžã§ã¯ãã§äœæ¥ããã«ã¯ã Visual Studio Codeã䜿çšããŸãã ã³ãã³ãã©ã€ã³ãããã°ã©ã ã«çµã¿èŸŒãŸãã Ctrl + `ãä»ããŠåŒã³åºãããããšãç¹ã«æ°ã«å
¥ã£ãŠããŸãã

ãããžã§ã¯ãNode.jsã空çœã«ããŸãã ãããè¡ãã«ã¯ãäžèšã®æ§é ã䜿çšããŠãããžã§ã¯ãçšã®ãã©ã«ããŒãäœæããã³ãã³ãã©ã€ã³ã§ãã®ãã©ã«ããŒã«ç§»åããŸããããã§ãã³ãã³ããåŒã³åºããŠpackage.json
ãã¡ã€ã«ãäœæããŸãã
npm init
è©³çŽ°ãªæ
å ±ãEnter
ãããªãå Žåã¯ã Enter
ãæŒãã ãã§ãã¹ãŠã®è³ªåã«çããããšãã§ããŸãã
ãããã®å Žåã§ãå¿
èŠã«ãªã3ã€ã®äžè¬çãªããã±ãŒãžãã€ã³ã¹ããŒã«ããŸãïŒ webpack
ã webpack-cli
ïŒ webpack-cli
ã®ã³ãã³ãã©ã€ã³ã§ã®äœæ¥ã¯å¥ã®ããã±ãŒãžã«åã蟌ãŸããŸããïŒããã³webpack-dev-server
ïŒä¿åããããããžã§ã¯ãã®å€æŽããã©ãŠã¶ãŒã«ããã«è¡šç€ºãããããã«ããŒã«ã«ãµãŒããŒãèµ·åããããïŒ ã
npm install webpack webpack-cli webpack-dev-server --save-dev
package.jsonãã¡ã€ã«ã¯æ¬¡ã®ããã«ãªããŸãã { "name": "static-site-webpack-habr", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "license": "ISC", "devDependencies": { "webpack": "^4.1.1", "webpack-cli": "^2.0.11", "webpack-dev-server": "^3.1.1" } }
package-lock.json
ãã¡ã€ã«ãäœæãããŸãããããã«ã¯äžåè§ŠããŸããã ãã ããgitãªããžããªã§ã¯ã node_modules
ãã©ã«ããŒãšã¯ç°ãªãããã®ãã¡ã€ã«ã远å ããå¿
èŠããããŸãnode_modules
ãã©ã«ããŒã¯ãgitã䜿çšããå Žåã¯.gitignore
ãã¡ã€ã«ã«æžã蟌ãå¿
èŠããããŸãã
JavaScriptãæ§ç¯ãã
Webpackã¯äž»ã«jsãã¡ã€ã«ãäœæããããã«äœæãããŠããããããã®éšåãæãç°¡åã§ãã ãã©ãŠã¶ã§ãµããŒããããŠããªãES2015ã®ææ°ã®åœ¢åŒã§javascriptãèšè¿°ã§ããããã«ãããã±ãŒãžbabel-core
ã babel-loader
ã babel-preset-env
ãã€ã³ã¹ããŒã«ããŸãã
npm install babel-core babel-loader babel-preset-env --save-dev
次ã®å
容ã§webpack.config.js
èšå®webpack.config.js
ãäœæããåŸïŒ
const path = require('path'); module.exports = { entry: [ './src/js/index.js', ], output: { filename: './js/bundle.js' }, devtool: "source-map", module: { rules: [{ test: /\.js$/, include: path.resolve(__dirname, 'src/js'), use: { loader: 'babel-loader', options: { presets: 'env' } } }, ] }, plugins: [ ] };
entry
ã»ã¯ã·ã§ã³ïŒ entry
ãã€ã³ãïŒã§ã¯ãåéããjsãã¡ã€ã«ã瀺ãã output
ã»ã¯ã·ã§ã³ã§ã¯ãåéãããã¡ã€ã«ãé
眮ãããdist
ãã©ã«ãã®ãã¹ã瀺ããŸãã output
ãã¹ã®webpack 4ã§ã¯ã dist
ãã©ã«ããŒèªäœãæå®ããå¿
èŠããªãããšã«æ³šæããŠãã ããïŒ ãããŠãã¯ããç§ã¯ããã1ã€ã®webpackãã¡ã€ã«ã§å¥œãã§ã¯ãªãå Žåã¯ãçžå¯Ÿãã¹ãæžãå¿
èŠãããå Žåããããä»ã®å Žåã¯ç¹å¥ãªãã©ã«ããŒã«çžå¯Ÿãã¹ãæžãå¿
èŠãããã3çªç®ã®å Žåã¯çµ¶å¯Ÿãã¹ãå¿
èŠã§ãïŒããšãã°ããã®ã³ãã³ãpath.resolve(__dirname, 'src/js')
ãããååŸããŸãã path.resolve(__dirname, 'src/js')
ïŒã
ãŸãã devtool
ãã©ã¡ãŒã¿ãŒå€ã¯source-map
çããèšå®ããsource-map
ãããã«ãããjsããã³cssãã¡ã€ã«ã®ãœãŒã¹ããããäœæã§ããŸãã
ç¹å®ã®ãã¡ã€ã«ïŒæ¡åŒµåãå ŽæïŒãåŠçããã«ã¯ãwebpackã®rules
ã»ã¯ã·ã§ã³ã«ã«ãŒã«ãäœæãrules
ã ããã§ããã¹ãŠã®jsãã¡ã€ã«ãBabelãã©ã³ã¹ã¬ãŒã¿ã«æž¡ããšããã«ãŒã«ããããŸããBabelãã©ã³ã¹ã¬ãŒã¿ã¯ãæ°ããäœæãããES2015ããã©ãŠã¶ãçè§£ã§ããæšæºã®javascriptããŒãžã§ã³ã«å€æããŸãã
ãã¹ãã±ãŒã¹ã§ã¯ãBoostrap 4ã«ããŒãžã課ããŠããŸãããããã£ãŠã bootstrap
ã jquery
ã popper.js
3ã€ã®ããã±ãŒãžãã€ã³ã¹ããŒã«ããå¿
èŠããããŸãã ããŒãã¹ãã©ããã§ãªã³ããã³ãã§ã€ã³ã¹ããŒã«ãã2çªç®ãš3çªç®ã®ããã±ãŒãžã
npm install bootstrap jquery popper.js --save
ãããã®3ã€ã®ããã±ãŒãžã¯ããµã€ãã§ã¯ãªããã¢ã»ã³ããªçšã«å¿
èŠã§ããããšã«æ³šæããŠãã ããã ãããã£ãŠããããã®ããã±ãŒãžã¯--save-dev
ã§ã¯ãªã--save-dev
ãã©ã°ã§ã€ã³ã¹ããŒã«ããŸãã
ããã§ã index.js
ãã¡ã€ã«ã®äœæãéå§ã§ããŸãã
import jQuery from 'jquery'; import popper from 'popper.js'; import bootstrap from 'bootstrap'; jQuery(function() { jQuery('body').css('color', 'blue'); });
ã«ã¹ã¿ã ã³ãŒãã®äŸãšããŠãjsã¯ããã¹ãã®è²ãéã«å¡ãçŽããŸããã
ããã§ãjsãã¡ã€ã«ã®ãã«ãã«é²ãããšãã§ããŸãã ãããè¡ãã«ã¯ã scripts
ã»ã¯ã·ã§ã³ã®package.json
ãã¡ã€ã«ã«ã次ã®npmã¹ã¯ãªãããèšè¿°ããŸãã
"scripts": { "dev": "webpack --mode development", "build": "webpack --mode production", "watch": "webpack --mode development --watch", "start": "webpack-dev-server --mode development --open" },
ããã§ãã³ãã³ãã©ã€ã³ã§npm run devè¡ãå®è¡ãããšããããžã§ã¯ããã¢ã»ã³ãã«ããïŒcssããã³htmlãã¡ã€ã«ããã®ã³ãã³ãã«ãã£ãŠåéãããŸãïŒã bundle.js
ããã³bundle.js.map
ãã¡ã€ã«ã/dist/js
bundle.js.map
ã
npm run buildã³ãã³ããå®è¡ãããšããããžã§ã¯ããã¢ã»ã³ãã«ãããŸãããæçµçãªãã®ïŒæé©åãæå€§ãã¡ã€ã«æå°åïŒã¯ãã¹ãã£ã³ã°ã«ã¢ããããŒãã§ããŸãã
npm run watchãéå§ãããšã倿Žããããã¡ã€ã«ãèªåçã«è¿œå ããããããžã§ã¯ããã¡ã€ã«ãžã®å€æŽãèªåçã«è¡šç€ºããã¢ãŒããéå§ãããŸãã ã¯ããã³ãã³ãã©ã€ã³ã§ãã®ã¢ãŒããç¡å¹ã«ããïŒããšãã°ãä»ã®ã³ãã³ããæžãïŒã«ã¯ã Ctrl + C
æŒããŸãïŒå°ãªããšãPowerShellã§ïŒã
npm run startãèµ·åãããšãããŒã«ã«ãµãŒããŒãèµ·åããhtmlããŒãžãèµ·åãããã¡ã€ã«ã®å€æŽã远跡ãããŸãã ãã ããçŸæç¹ã§ã¯ãHTMLããŒãžã®ã¢ã»ã³ããªã远å ãããŠããªãããããã®ã³ãã³ãã¯äœ¿çšããŠããŸããã
ãããžã§ã¯ããã«ãã¢ãŒãã¯ã dist
ãã©ã«ããŒå
ã®ãã¡ã€ã«ãäœæãŸãã¯äžæžãããŸãã ãã ããç°ãªãã¢ã»ã³ããªã䜿çšãããããžã§ã¯ãã®éçºäžã«ããã¡ã€ã«ã®ååã倿Žããããåé€ãããã§ããŸãã ãŸããWebpackã¯ã以åã®ãã«ãã§æ®ã£ãäžèŠãªãã¡ã€ã«ãdist
ãã©ã«ããŒããåé€ãããããšãä¿èšŒããŸããã ãããã£ãŠãåãããžã§ã¯ãããã«ãããåã«dist
ãã©ã«ããŒãã¯ãªã¢ããå¥ã®clean-webpack-plugin
ã远å ããŸãã
2018.04.11ããæŽæ° clean-webpack-plugin
ãæŸæ£ããªããã°ãªãclean-webpack-plugin
ã ãªãã§ïŒ npm run start
webpack-dev-server --mode development --open
ïŒ webpack-dev-server --mode development --open
ïŒã§webpack-dev-server --mode development --open
ãwebpackã¯ãã¡ã€ã«ãdist
ãã©ã«ããŒã«ä¿åããã«èªåçã«ã³ã³ãã€ã«ããŸãã ããã¯æ£åžžã§ãã ãã ããåæã«clean-webpack-plugin
ãååšããããã dist
ãã©ã«ããŒã¯æ¶å»ããclean-webpack-plugin
ã ãã®çµæãããŒã«ã«ãµãŒããŒã®åäœã¢ãŒãã§ã¯ã dist
ãã©ã«ããŒã空ã«ãªãããããgitã®äœæ¥ã«æªåœ±é¿ãåãŒããŸãïŒç§ã®ããã«gitãªããžããªã«ãããžã§ã¯ãã¢ã»ã³ããªãä¿åããå Žåã®ã¿ïŒãåãµãŒããŒã®èµ·ååŸãåé€ããããã¡ã€ã«ã«ããå€ãã®å€æŽã衚瀺ãããŸãã ããšãã°ã npm run build-and-beautify
ïŒä»¥äžã®ãã®ã³ãã³ãã«ã€ããŠïŒã®ããã«ã npm run build-and-beautify
äžã«ã®ã¿dist
ãã©ã«ããŒãã¯ãªãŒã³ã¢ããããããšäŸ¿å©ã§ãã clean-webpack-plugin
å¿
èŠãªæ¹æ³ã§æ§æã§ããŸããã§ããã ãããã£ãŠãå¥ã®del-cli
ã䜿çšãdel-cli
ãããã¯ãwebpackã«æ¥ç¶ãããŠããããåå¥ã«åäœããŸãã
npm install del-cli --save-dev
package.json
ãã¡ã€ã«ã«å€æŽãå ããŸãã
{ ... "scripts": { ... "clear": "del-cli dist" }, ... }
CSSãã¡ã€ã«ã¢ã»ã³ããª
src/scss
ãäºçŽããSCSSãã¡ã€ã«ããCSSãã¡ã€ã«ãåéãsrc/scss
ã ãã®äžã«ãããšãã°æ¬¡ã®å
容ã®style.scss
ãã¡ã€ã«ãäœæããŸãã
$font-stack: -apple-system, BlinkMacSystemFont,Roboto,'Open Sans','Helvetica Neue',sans-serif; @import "~bootstrap/scss/bootstrap"; @font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400; src: url(../fonts/Roboto-Regular.ttf); } body { font-family: $font-stack; #logo { width: 10rem; } .container { img { width: 20rem; } } }
Bootstrapã¹ã¿ã€ã«ã¯ãCSSãã¡ã€ã«ã§ã¯ãªãSSSïŒ @import "node_modules/bootstrap/scss/bootstrap"
@import "~bootstrap/scss/bootstrap";
ïŒãå¿
èŠã«å¿ããŠãã©ã€ãã©ãªã®ç¹å®ã®ããããã£ãæžãæããããããã¯ã¹ã€ã³ã䜿çšãããããããšãã§ããŸãã jsãã¡ã€ã«ã®ã¢ã»ã³ããªäžã«jsãã¡ã€ã«ãBootstrapã©ã€ãã©ãªã«æ¥ç¶ãããšãã«Webpackãå¿
èŠãªãã¡ã€ã«ã®å ŽæãèªèããŠããå Žåãã¹ã¿ã€ã«ãæ¥ç¶ãããšãã«node_modules
ãã©ã«ããŒãžã®ãã¹ãæå®ããå¿
èŠããããŸãã
cssãã¡ã€ã«ãåŠçããã«ã¯ã node-sass
ã sass-loader
ã css-loader
ãããã³extract-text-webpack-plugin
ã¢ãžã¥ãŒã«ãå¿
èŠã§ãïŒ extract-text-webpack-plugin
ã®æ¬¡ã®ããŒãžã§ã³ã§ã¯ãæåŸã®ãã©ã°ã€ã³ã¯ãããå¿
èŠãšããªããªããŸãïŒã
éèŠïŒ å·çæç¹ã§ã¯ãå®å®ããŒãžã§ã³ã®extract-text-webpack-plugin
ã¯Webpack 4ã§åäœããŸããããããã£ãŠã @next
ãä»ããŠããŒã¿ããŒãžã§ã³ãã€ã³ã¹ããŒã«ããå¿
èŠããããŸãã
npm install node-sass sass-loader css-loader extract-text-webpack-plugin@next --save-dev
ãã¹ãŠã®ãã©ã°ã€ã³ãéåžžã®æ¹æ³ã§ããã«ã€ã³ã¹ããŒã«ã§ããããã«ãªãããšãé¡ã£ãŠããŸãã
npm install node-sass sass-loader css-loader extract-text-webpack-plugin --save-dev
webpack.config.js
ãæ¬¡ã®å€æŽã远å ããŸãã
... const ExtractTextPlugin = require("extract-text-webpack-plugin"); ... module.exports = { entry: [ ... './src/scss/style.scss' ], ... module: { rules: [{ ... { test: /\.(sass|scss)$/, include: path.resolve(__dirname, 'src/scss'), use: ExtractTextPlugin.extract({ use: [{ loader: "css-loader", options: { sourceMap: true, minimize: true, url: false } }, { loader: "sass-loader", options: { sourceMap: true } } ] }) }, ] }, plugins: [ new ExtractTextPlugin({ filename: './css/style.bundle.css', allChunks: true, }), ... ] };
ãšã³ããªentry
ãã€ã³ãã«æ°ããå
¥åãã¡ã€ã«style.scss
ã远å ããŸããããåºåãã¡ã€ã«ã¯output
ã§ã¯æå®ãããã plugins
ã»ã¯ã·ã§ã³ã®ExtractTextPluginãã©ã°ã€ã³ã®åŒã³åºãã§æå®ãããŠããããšã«æ³šæããŠãã ããã sass-loader
ããã³css-loader
ããã±ãŒãžã®sourceMapãœãŒã¹ãããã®ãµããŒããå«ãŸããŠããŸãã
ãŸãã style-loader
ããã±ãŒãžããªãããšã«ãæ°ä»ãããšãã§ããŸãã style-loader
ããã±ãŒãžã¯ãWebpackã§cssã䜿çšãããšãã«æãããèšåãããŸãã ãã®ããã±ãŒãžã¯cssã³ãŒããHTMLãã¡ã€ã«ã«åã蟌ã¿ãŸããããã¯åäžããŒãžã®ã¢ããªã±ãŒã·ã§ã³ã«ã¯äŸ¿å©ã§ãããè€æ°ããŒãžã®ã¢ããªã±ãŒã·ã§ã³ã«ã¯äŸ¿å©ã§ã¯ãããŸããã
ãããŠãæãç©è°ãéžãç¬éã css-loader
ããã±ãŒãžã®å Žåã false
çããurl
ãã©ã¡ãŒã¿ãŒã远å ããŸããã ãªãã§ïŒ ããã©ã«ãã§ã¯ã url=true
ã§ãããCSSãæ§ç¯ãããšãã«Webpackãå€éšãã¡ã€ã«ãžã®ãªã³ã¯ãèŠã€ããå ŽåïŒèæ¯ç»åããã©ã³ãïŒããšãã°ããã®å Žåã url(../fonts/Roboto-Regular.ttf)
ãã©ã³ããã¡ã€ã«url(../fonts/Roboto-Regular.ttf)
ãžã®ãªã³ã¯ããããŸãïŒããã圌ã¯ãããã®ãã¡ã€ã«ãäœããã®åœ¢ã§åŠçããããã«é Œã¿ãŸãã ãã®ãããæãäžè¬çã«äœ¿çšãããããã±ãŒãžã¯ã file-loader
ïŒãã«ããã©ã«ããŒã«ãã¡ã€ã«ãã³ããŒããïŒãŸãã¯url-loader
ïŒHTMLã³ãŒãã«åã蟌ã¿ã詊ã¿ãå°ããªãã¡ã€ã«ïŒã§ãã ãã®å Žåãã¢ã»ã³ãã«ãããcsså
ã®ãã¡ã€ã«ãžã®æå®ã®çžå¯Ÿãã¹ã倿Žã§ããŸãã
ããããå®éã«ã¯ã©ããªåé¡ã«ééããŸãããïŒ SCSSã³ãŒããsrc/scss
ããããŸãã SCSSã³ãŒãã§åç
§ãããç»åãå«ãsrc/img
ãã©ã«ããŒããããŸãã ãã¹ãŠãé 調ã§ãã ããããããšãã°ããµãŒãããŒãã£ã®ã©ã€ãã©ãªããµã€ãã«æ¥ç¶ããå¿
èŠããããŸããïŒããšãã°ãlightgalleryïŒã 圌女ã®SCSSã³ãŒãã¯node_modules/lightgallery/src/sass
ã«ããnode_modules/lightgallery/src/sass
ããã®ãã©ã«ããŒã¯ãçžå¯Ÿãã¹ãä»ããŠnode_modules/lightgallery/src/img
ãã©ã«ããŒã®åçãåç
§ããŸãã ãŸãã style.scss
ã©ã€ãã©ãªã¹ã¿ã€ã«ã远å ãããšã file-loader
ã¯ã©ãã«ãããã§ã¯ãªãã src/img
ãã©ã«ããŒå
ã§lightgallery
ã©ã€ãã©ãªã®åçãæ¢ããŸãã ãããŠãç§ã¯ãããå
æã§ããŸããã§ããã
æŽæ°ãã Odrinã瀺åããããã«ã resolve-url-loaderããã±ãŒãžãšfile-loaderã䜿çšããŠãæåŸã®åé¡ã«å¯ŸåŠã§ããŸãã
ãœãªã¥ãŒã·ã§ã³äŸ ... module.exports = { ... module: { rules: [ ... { test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: {name: 'img/[name].[ext]'} } ] }, { test: /\.(sass|scss)$/, include: path.resolve(__dirname, 'src/scss'), use: ExtractTextPlugin.extract({ use: [{ loader: "css-loader", options: { sourceMap: true, minimize: true//, //url: false } }, { loader: "resolve-url-loader" }, { loader: "sass-loader", options: { sourceMap: true } } ] }) } ... ] }, ... };
ã€ãŸããçžå¯Ÿãã¹ã®ä»£ããã«resolve-url-loaderããã±ãŒãžãwebpackãçè§£ãããã¹ãèšå®ããŸãã ãããŠããã§ã«ãã¡ã€ã«ããŒããŒã¯å¿
èŠãªãã¡ã€ã«ãã³ããŒããŸãã åé¡ã¯ããã¡ã€ã«ããŒããŒã®ååããããã£ã«ãããŸãã name: '[path]/[name].[ext]'
ãšããŠæå®ããå Žåname: '[path]/[name].[ext]'
ãç§ã®äŸã§ã¯ã dist\node_modules\lightgallery\src\img
ãã©ã«ããŒã¯ãç»åãæ¢ã«é
眮ãããŠããdistãã©ã«ããŒã«è¡šç€ºãããŸãã ããããcssã«ã¯ãã®ãã©ã«ããŒãžã®æ£ãããã¹ãç»é²ãããŸããããããã§ã¯ãããŸããã ãããã£ãŠããã¹ãªãã§ãã¡ã€ã«åãæå®ããããšããå§ãããŸãïŒããšãã°ã name: 'img/[name].[ext]'
ïŒã 確ãã«ããã¹ãŠã®åçã¯1ã€ã®ãã©ã«ããŒã«ç§»åããŸã-åžžã«åœ¹ç«ã€ãšã¯éããŸããã
ãããã£ãŠã url=false
ã«èšå®ãããšãSCSSã³ãŒãå
ã®ãã¡ã€ã«ãžã®ãã¹ãŠã®ãªã³ã¯ã«è§Šããããã¹ã倿Žããããã¡ã€ã«ãã³ããŒãŸãã¯åã蟌ã¿ãããªããšèšããŸããåŸã§åå¥ã«åŠçããŸãã ããããããã®è§£æ±ºçã¯äžé©åã§ãããããé©åãªã¢ãããŒããææ¡ããŸãã
HTMLããŒãžã¢ã»ã³ããª
楜ããéšåã«ç§»ããŸããããHTMLããŒãžãçµã¿ç«ãŠãã®ã¯ãç§ã«ãšã£ãп倧ã®å°é£ã§ããã
HTMLããŒãžãäœæããã«ã¯ãããŸããŸãªã¿ã€ãã®ãã³ãã¬ãŒããšã³ãžã³ããµããŒãããhtml-webpack-plugin
ã䜿çšããŸãã ãŸãã raw-loader
ããã±ãŒãžãå¿
èŠã«ãªããŸãã
npm install html-webpack-plugin raw-loader --save-dev
HTMLãã³ãã¬ãŒããšã³ãžã³ãšããŠãããã©ã«ãã®ãã³ãã¬ãŒããšã³ãžã³lodashã䜿çšããŸãã ããã¯ãã¢ã»ã³ããªåã®å
žåçãªHTMLããŒãžã®å€èгã§ãã
<% var data = { title: " | ", author: "Harrix" }; %> <%= _.template(require('./../includes/header.html'))(data) %> <p>text</p> <%= _.template(require('./../includes/footer.html'))(data) %>
æåã«ã data
倿°ã«ããã®ããŒãžã§äœ¿çšãããã¹ãŠã®ããŒãžå€æ°ãç»é²ããŸãã æ¬¡ã«ã _.template(require())
ã _.template(require())
ã_.template(require())
ãŠããããŒãšããã¿ãŒã®ãã³ãã¬ãŒããåã蟌ã¿ãŸãã
éèŠãªèª¬æã html-webpack-plugin
ãä»ããHTMLããŒãžã®ã¢ã»ã³ãã«ã«é¢ããèšäºã§ã¯ãéåžžãåã蟌ã¿ãã³ãã¬ãŒãã¯æ¬¡ã®ã³ãã³ãã§ç°¡åã«æ¥ç¶ã§ããŸãã
require('html-loader!./../includes/header.html')
ãã ããåæã«ããããã®åã蟌ã¿ãã³ãã¬ãŒãã§ã¯lodashæ§æã¯æ©èœããŸããïŒããããªãèµ·ããã®ããŸã ããããŸããïŒã ãŸããããŒã¿å€æ°ããã®data
ã¯ããã«è»¢éãããŸããã ãã®ãããwebpackã«ãlodashãã³ãã¬ãŒããšããŠåŠçããå¿
èŠããããã³ãã¬ãŒããåã蟌ãããšã匷å¶ããŸãã
ããã§ãã€ã³ã©ã€ã³ãã³ãã¬ãŒãã§æ¬æ Œçãªlodashæ§æã䜿çšã§ããŸãã 以äžã®header.html
ãã¡ã€ã«header.html
ã§ã¯ã <%=title%>
ãŠèšäºã®ã¿ã€ãã«<%=title%>
å°å·ããŸãã
<!doctype html> <html lang="ru"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="shortcut icon" href="favicon/favicon.ico"> <link rel="stylesheet" href="css/style.bundle.css"> <title><%=title%></title> </head> <body> <header><img src="img/logo.svg" id="logo"></header>
html-webpack-pluginããã±ãŒãžã«ã¯ãè€æ°ã®HTMLããŒãžãçæããæ©èœããããŸãã
plugins: [ new HtmlWebpackPlugin(), // Generates default index.html new HtmlWebpackPlugin({ // Also generate a test.html filename: 'test.html', template: 'src/assets/test.html' }) ]
ãããããã©ã°ã€ã³ã®ç¬èªã®ã€ã³ã¹ã¿ã³ã¹ãäœæããåããŒãžãåŠæ¹ããããšã¯ééããªãè¯ããããŸããã ãã®ããã src/html/views
ãã©ã«ããŒå
ã®ãã¹ãŠã®HTMLãã¡ã€ã«ãæ€çŽ¢ããŠãã®ããã»ã¹ãèªååãããããã®new HtmlWebpackPlugin()
ç¬èªã®ããŒãžã§ã³ãäœæããŸãã
ãããè¡ãã«ã¯ã webpack.config.js
ãã¡ã€ã«ã«æ¬¡ã®å€æŽãwebpack.config.js
ãŸãã
... const HtmlWebpackPlugin = require('html-webpack-plugin'); const fs = require('fs') function generateHtmlPlugins(templateDir) { const templateFiles = fs.readdirSync(path.resolve(__dirname, templateDir)); return templateFiles.map(item => { const parts = item.split('.'); const name = parts[0]; const extension = parts[1]; return new HtmlWebpackPlugin({ filename: `${name}.html`, template: path.resolve(__dirname, `${templateDir}/${name}.${extension}`), inject: false, }) }) } const htmlPlugins = generateHtmlPlugins('./src/html/views') module.exports = { module: { ... { test: /\.html$/, include: path.resolve(__dirname, 'src/html/includes'), use: ['raw-loader'] }, ] }, plugins: [ ... ].concat(htmlPlugins) };
generateHtmlPlugins
颿°ã¯ããã¹ãŠã®HTMLããŒãžãæ€çŽ¢ããŸãã 颿°ã³ãŒãã«ã¯ã inject: false
èšå®ããããŸããããã¯ãWebpackã«jsããã³cssãã¡ã€ã«ãªã³ã¯ãHTMLã³ãŒãã«åã蟌ãå¿
èŠããªãããšãäŒããŸããheader.htmlããã³footer.html
ã§ãã¹ãŠãæåã§è¡ããŸãã
åã蟌ãŸãããã³ãã¬ãŒãã¯ãæãããææ¡ãããhtml-loader
ã§ã¯ãªãã raw-loader
ãã©ã°ã€ã³ïŒãã¡ã€ã«ã®å
容ã¯åã«ããã¹ããšããŠããŒããããïŒã«ãã£ãŠåŠçãããããšã«ã泚æããŠãã ããã ãŸããCSSã®å Žåãšåæ§ã«ã file-loader
ãŸãã¯url-loader
ããã±ãŒãžã¯äœ¿çšããŸããã
ãããŠãHTMLãæ±ãæåŸã®ãªãã·ã§ã³ã®ç¬éãæ®ã£ãŠããŸãã JavaScriptãã¡ã€ã«ãšCSSãã¡ã€ã«ã¯æå°åãããŸãã ããããç§ã¯HTMLãã¡ã€ã«ãäœæããéã«çŸãããçž®å°ããŸããã ãããã£ãŠããã¹ãŠã®HTMLãã¡ã€ã«ãã¢ã»ã³ãã«ããåŸãäœããã®çŸåãã©ã°ã€ã³ã§ãããã調ã¹ãããšæããŸãã ãããŠãããã§ã»ããã¢ãããåŸ
ã£ãŠããŸãããWebpackã§ãããè¡ãæ¹æ³ãèŠã€ãããŸããã§ããã åé¡ã¯ãåã蟌ã¿ãã³ãã¬ãŒãã®æ¿å
¥åŸã«ãã¡ã€ã«ãåŠçããå¿
èŠãããããšã§ãã
Webpackã«é¢ä¿ãªããããè¡ãããšãã§ããhtml-cliããã±ãŒãžãèŠã€ããŸããã ããããåœŒã¯æã«38åã®ã€ã³ã¹ããŒã«ãè¡ã£ãŠããŸãã ã€ãŸããããã¯2ã€ã®ãªãã·ã§ã³ãæå³ããŸããHTMLãã¡ã€ã«ãçŸããèŠããããã«èª°ãå¿
èŠãšããªãããç§ãç¥ããªãå¥ã®äžè¬çãªãœãªã¥ãŒã·ã§ã³ããããŸãã ãããŠããã®æ©èœã ãã®ããã«ãGulpã¯ãã蟌ã¿ãæãã§ããŸããã
ãã®ãã©ã°ã€ã³ãã€ã³ã¹ããŒã«ããŸãã
npm install html-cli --save-dev
ãŸãã package.json
ãã¡ã€ã«ã«ã¯ãWebpackã§äœæ¥ããåŸã2ã€ã®ã¹ããŒã¹ã§è¡šåœ¢åŒã®HTMLãã¡ã€ã«ãçŸãã衚瀺ããã¹ã¯ãªãããããã«2ã€èšè¿°ããŸãã
"scripts": { "build-and-beautify": "del-cli dist && webpack --mode production && html dist/*.html --indent-size 2", "beautify": "html dist/*.html --indent-size 2" },
2018.04.11ã®æŽæ° build-and-beautify
del-cli dist
ã«del-cli dist
ã远å ããããšã«æ³šæããŠãã ãããããã«ããã build-and-beautify
åã«dist
ãã©ã«ããŒãã¯ãªã¢ãããŸãã
ãããã£ãŠãæçµãã«ãã§ã¯ã* npm run buildã³ãã³ãã§ã¯ãªãã npm run build-and-beautifyã³ãã³ãã䜿çšããããšããå§ãããŸãã
æ®ãã®ãã¡ã€ã«ãã³ããŒãã
jsãcssãã¡ã€ã«ãHTMLããŒãžãçæããŸããã ç»åãã¡ã€ã«ããã©ã³ããªã©ãè§ŠããŠããªããã®ãã file-loader
ãurl-loader
æèããŠã³ããŒããŠããªããã®ããããŸãã ãããã£ãŠãæ®ãã®ãã¹ãŠã®ãã©ã«ããŒãcopy-webpack-plugin
ä»ããŠcopy-webpack-plugin
ã
npm install copy-webpack-plugin --save-dev
webpack.config.js
ãã¡ã€ã«webpack.config.js
ã倿Žãè¡ããŸãã
... const CopyWebpackPlugin= require('copy-webpack-plugin'); ... module.exports = { ... plugins: [ ... new CopyWebpackPlugin([{ from: './src/fonts', to: './fonts' }, { from: './src/favicon', to: './favicon' }, { from: './src/img', to: './img' }, { from: './src/uploads', to: './uploads' } ]), ]... };
ããã ãã§ã ããã§ã npm run build-and-beautifyã³ãã³ãã䜿çšããŠãããžã§ã¯ããåéããçµã¿ç«ãŠãããéçãµã€ããdist
ãã©ã«ããŒã«è¡šç€ºãããŸãã

èŠçŽãã¡ã€ã«
Package.jsonãã¡ã€ã«ïŒ { "name": "static-site-webpack-habr", "version": "1.0.0", "description": "HTML template", "main": "src/index.js", "scripts": { "dev": "webpack --mode development", "build": "webpack --mode production", "build-and-beautify": "del-cli dist && webpack --mode production && html dist/*.html --indent-size 2", "watch": "webpack --mode development --watch", "start": "webpack-dev-server --mode development --open", "beautify": "html dist/*.html --indent-size 2", "clear": "del-cli dist" }, "dependencies": { "bootstrap": "^4.1.0", "jquery": "^3.3.1", "popper.js": "^1.14.3" }, "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.3", "babel-preset-env": "^1.6.1", "copy-webpack-plugin": "^4.5.0", "css-loader": "^0.28.11", "del-cli": "^1.1.0", "extract-text-webpack-plugin": "^4.0.0-beta.0", "html-cli": "^1.0.0", "html-webpack-plugin": "^3.2.0", "node-sass": "^4.8.3", "raw-loader": "^0.5.1", "sass-loader": "^6.0.6", "webpack": "^4.5.0", "webpack-cli": "^2.0.14", "webpack-dev-server": "^3.1.3" } }
Webpack.config.jsãã¡ã€ã«ïŒ const path = require('path'); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const CopyWebpackPlugin = require('copy-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const fs = require('fs') function generateHtmlPlugins(templateDir) { const templateFiles = fs.readdirSync(path.resolve(__dirname, templateDir)); return templateFiles.map(item => { const parts = item.split('.'); const name = parts[0]; const extension = parts[1]; return new HtmlWebpackPlugin({ filename: `${name}.html`, template: path.resolve(__dirname, `${templateDir}/${name}.${extension}`), inject: false, }) }) } const htmlPlugins = generateHtmlPlugins('./src/html/views'); module.exports = { entry: [ './src/js/index.js', './src/scss/style.scss' ], output: { filename: './js/bundle.js' }, devtool: "source-map", module: { rules: [{ test: /\.js$/, include: path.resolve(__dirname, 'src/js'), use: { loader: 'babel-loader', options: { presets: 'env' } } }, { test: /\.(sass|scss)$/, include: path.resolve(__dirname, 'src/scss'), use: ExtractTextPlugin.extract({ use: [{ loader: "css-loader", options: { sourceMap: true, minimize: true, url: false } }, { loader: "sass-loader", options: { sourceMap: true } } ] }) }, { test: /\.html$/, include: path.resolve(__dirname, 'src/html/includes'), use: ['raw-loader'] }, ] }, plugins: [ new ExtractTextPlugin({ filename: './css/style.bundle.css', allChunks: true, }), new CopyWebpackPlugin([{ from: './src/fonts', to: './fonts' }, { from: './src/favicon', to: './favicon' }, { from: './src/img', to: './img' }, { from: './src/uploads', to: './uploads' } ]), ].concat(htmlPlugins) };
Index.htmlãã³ãã¬ãŒããã¡ã€ã«ïŒ <% var data = { title: " | ", author: "Harrix" }; %> <%= _.template(require('./../includes/header.html'))(data) %> <div class="container"> <p> .</p> <p><img src="uploads/test.jpg"></p> </div> <%= _.template(require('./../includes/footer.html'))(data) %>
Header.htmlããããŒãã³ãã¬ãŒããã¡ã€ã«ïŒ <!doctype html> <html lang="ru"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="shortcut icon" href="favicon/favicon.ico"> <link rel="stylesheet" href="css/style.bundle.css"> <title><%=title%></title> </head> <body> <header><img src="img/logo.svg" id="logo"></header>
Footer.htmlãã³ãã¬ãŒããã¡ã€ã«ïŒ <footer><%=author%></footer> <script src="js/bundle.js"></script> </body> </html>
çæãããindex.htmlïŒ <!doctype html> <html lang="ru"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="shortcut icon" href="favicon/favicon.ico"> <link rel="stylesheet" href="css/style.bundle.css"> <title> | </title> </head> <body> <header><img src="img/logo.svg" id="logo"></header> <div class="container"> <p> .</p> <p><img src="uploads/test.jpg"></p> </div> <footer>Harrix</footer> <script src="js/bundle.js"></script> </body> </html>
ãœãŒã¹ã³ãŒã
ã¬ãã¥ãŒãããããžã§ã¯ãã®ãããªããžããªã«ãªã³ã¯ããŸãã