Webpack 4のシンプルな静的サイト







多数の記事(たとえば、 この記事)を読んだ後、「恐竜」アプローチを使用して単純なサイトを作成するときに、Node.jsを使用した最新のアプローチに切り替えることにしました。 以下は、 Webpack 4を使用して単純な静的サイトを構築する解析例です。 問題を解決するための指示が見つからなかったため、この記事は書かれました。すべてを断片的に収集しなければなりませんでした。







問題の声明



サイトは、独自のCSSスタイルと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>
      
      





ソースコード



レビューしたプロジェクトのあるリポジトリにリンクします。








All Articles