I'm trying to create a setup with static HTML partials using the HTML Webpack Plugin, but running into some errors. This is my current config:
webpack.config.js
const webpack = require('webpack'); const path = require('path'); const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const OptimizeCSSAssets = require('optimize-css-assets-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); let config = { entry: './src/index.js', output: { path: path.resolve(__dirname, './public'), filename: 'app.js' }, module: { loaders: [{ test: /\.html$/, loader: 'html-loader' }], rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }, { test: /\.scss$/, use: ['css-hot-loader'].concat(ExtractTextWebpackPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'sass-loader', 'postcss-loader'], })), }, { test: /\.(jpe?g|png|gif|svg)$/i, loaders: ['file-loader?context=src/assets/images/&name=images/[path][name].[ext]', { loader: 'image-webpack-loader', query: { mozjpeg: { progressive: true, }, gifsicle: { interlaced: false, }, optipng: { optimizationLevel: 4, }, pngquant: { quality: '75-90', speed: 3, }, }, }], exclude: /node_modules/, include: __dirname, }, ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/template.html.ejs' }), new ExtractTextWebpackPlugin('main.css') ], devServer: { contentBase: path.resolve(__dirname, './public'), historyApiFallback: true, inline: true, open: true }, devtool: 'eval-source-map' } module.exports = config; if (process.env.NODE_ENV === 'production') { module.exports.plugins.push( new webpack.optimize.UglifyJsPlugin(), new OptimizeCSSAssets() ); }
template.html.ejs (located under ./src
)
<%=require('./header.html')%> <body> testing schmesting </body> <%=require('./footer.html')%> </html>
(footer.html and header.html are located under ./src
)
Edit: Updated the code, still issues:
"ERROR in Error: Child compilation failed: Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (1:0) Module parse failed: Unexpected token (1:2) You may need an appropriate loader to handle this file type."
1 Answers
Answers 1
EDIT
(EDIT: 2017-12-20 move "loaders" to "rules")
By default, "html-webpack-plugin" parses the template as "underscore" (also called lodash) template, your "template.html" is nothing wrong, the error is caused by webpack failed to resolve 'html-loader' for your "template.html" <%= require('html-loader!./footer.html') %>
, so you need to install "html-loader" for webpack, and configure it:
In command line:
npm install html-loader
And configure it for webpack, edit webpack.config.js
:
... module: { rules: [ // ... { test: /\.html$/, // tells webpack to use this loader for all ".html" files loader: 'html-loader' } ] }
By now you can run "webpack" you'll see no error, BUT the generated "index.html" is not you expected, because your template file has ".html" extension, webpack now use "html-loader" to load "template.html" instead of default "lodash loader", to solve this you can rename "template.html" to "template.html.ejs" (or any other extension) to make "html-webpack-plugin" fallback. Besides there is a little bit more change on "template.html", remove "html-loader!" from it:
<%= require('./footer.html') %>
now it should work.
EDIT Post my code for reference :
/src/template.html.ejs
<!DOCTYPE html> <html lang="en"> <head> <title>test</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>template</h1> <%=require('./footer.html')%> </body> </html>
/src/footer.html
<footer>this is a footer</footer>
/webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); let config = { entry: { index: './src/js/index' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js' }, module: { rules: [ { test: /\.html$/, loader: 'html-loader' } ], }, plugins: [ new HtmlWebpackPlugin({ template: './src/template.html.ejs' }) ] } module.exports = config;
/package.json
{ "name": "test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "html-loader": "^0.5.1", "html-webpack-plugin": "^2.30.1", "webpack": "^3.10.0" } }
/src/js/index.js
console.log("A test page!");
environment:
- webpack 3.10.0
- npm 5.6.0
content of "/dist/index.html" after run webpack:
<!DOCTYPE html> <html lang="en"> <head> <title>test</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>template</h1> <footer>this is a footer</footer> <script type="text/javascript" src="index.js"></script></body> </html>
As you can see content of "footer.html" is correctly inserted.
OLD ANSWER
Approach 1: Using "es6" template
- Install "html-loader" by
npm install html-loader
- Add "html-loader" to your "webpack.config.js" for loading files with ".html" extension, like:
module: { rules: [{ test: /\.html$/, loader: 'html-loader' }], }
- Add
interpolate
flag to enable interpolation syntax for ES6 template strings, like so:
plugins: [ new HtmlWebpackPlugin({ template: '!!html-loader?interpolate!src/template.html' }) ]
- Modify your
template.html
to match ES6 template:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> template </body> ${require('./footer.html')} </html>
- Run
webpack
, it'll work
Approach 2: Using "underscore" template
Follow "approach 1" step 1 and 2, and then:
- Rename "template.html" to "template.html.ejs"
- Change
template: './src/template.html'
totemplate: './src/template.html.ejs'
in "webpack.config.js" - Run webpack
0 comments:
Post a Comment