I'm trying to set up an angular project using Webpack but I can't figure out how to reference images from within html templates and have them included in the build.
My project tree is as follows:
package.json app/ - images/ - foo.png - scripts/ - styles/ - templates/
I'm trying to use html-loader
along with url-loader
and file-loader
but it's just not happening.
This is an example template: app/templates/foo.html
<img src="../images/foo.png" />
Problem #1: I would like to be able to reference images relative to app/
. Right now, the paths need to be relative to the template file and this will get ugly very quickly (../../../images/foo.png
).
Problem #2: Even if I specify the relative path, as I have done above, the project builds successfully but nothing really happens. The paths are left as-is and no images appear in dist/
.
Here is my webpack config:
var path = require('path'); var webpack = require('webpack'); var ngminPlugin = require('ngmin-webpack-plugin'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); var ngAnnotatePlugin = require('ng-annotate-webpack-plugin'); module.exports = function(config, env) { var appRoot = path.join(__dirname, 'app/') if(!env) env = 'development'; var webpackConfig = { cache: true, debug: true, contentBase: appRoot, entry: { app: path.join(appRoot, '/scripts/app.coffee') }, output: { path: path.join(__dirname, 'dist/), publicPath: '/', libraryTarget: 'var', filename: 'scripts/[name].[hash].js', chunkFilename: '[name].[chunkhash].js' }, module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") }, { test: /\.scss$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader!sass-loader?outputStyle=expanded&includePaths[]=./node_modules/foundation/scss/') }, { test: /\.coffee$/, loader: 'coffee-loader' }, { loader: 'ngtemplate?relativeTo=' + (path.resolve(__dirname, './app')) + '/!html' }, { test: /\.png$/, loader: "url-loader?limit=100000&mimetype=image/png&name=[path][name].[hash].[ext]" }, { test: /\.jpg$/, loader: "file-loader?name=[path][name].[hash].[ext]" }, { test: /\.(woff|woff2)(\?(.*))?$/, loader: 'url?prefix=factorynts/&limit=5000&mimetype=application/font-woff' }, { test: /\.ttf(\?(.*))?$/, loader: 'file?prefix=fonts/' }, { test: /\.eot(\?(.*))?$/, loader: 'file?prefix=fonts/' }, { test: /\.svg(\?(.*))?$/, loader: 'file?prefix=fonts/' }, { test: /\.json$/, loader: 'json' } ] }, resolve: { extensions: [ '', '.js', '.coffee', '.scss', '.css' ], root: [appRoot], }, singleRun: true, plugins: [ new webpack.ContextReplacementPlugin(/.*$/, /a^/), new webpack.ProvidePlugin({ '_': 'lodash' }), new ExtractTextPlugin("styles/[name].[chunkhash].css", {allChunks: true}), new HtmlWebpackPlugin({ template: appRoot + '/app.html', filename: 'app.html', inject: 'body', chunks: ['app'] }) ], devtool: 'eval' } if(env === 'production') { webpackConfig.plugins = webpackConfig.plugins.concat( new ngAnnotatePlugin(), new webpack.optimize.UglifyJsPlugin(), new webpack.DefinePlugin({ 'process-env': { 'NODE_ENV': JSON.stringify('production') } }), new webpack.optimize.DedupePlugin(), new webpack.optimize.UglifyJsPlugin() ); webpackConfig.devtool = false; webpackConfig.debug = false; } return webpackConfig;
}
You can use file-loader to extract images. Then using html-loader you can specify which tag-attribute combination should be processed by this loader via the query parameter attrs .
This means Webpack has successfully bundled both our logic from src/index. js and HTML from src/index. html into the dist directory, even automatically linking them together for us. And this is just the beginning of what Webpack can do!
Disclaimer: html-loader is a third-party package maintained by community members, it potentially does not have the same support, security policy or license as webpack, and it is not maintained by webpack. Exports HTML as string. HTML is minimized when the compiler demands.
If you are using HTML templates in Webpack 2, in addition to use the file-loader you need to change in your HTML:
<img src="../images/foo.png" />
to this
<img src=<%=require("../images/foo.png")%> />
file
loader:.
loaders: [{ // JS LOADER test: /\.js$/, loader: 'babel-loader?optional[]=runtime', exclude: /node_modules/ }, { // ASSET LOADER test: /\.(woff|woff2|ttf|eot)$/, loader: 'file-loader' }, { //IMAGE LOADER test: /\.(jpe?g|png|gif|svg)$/i, loader:'file-loader' }, { // HTML LOADER test: /\.html$/, loader: 'html-loader' }, { //SCSS LOADER test: /\.scss$/, loaders: ["style-loader", "css-loader", "sass-loader?indentedSyntax"] } ]
Good Luck
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With