Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include direct link to webpack entry points in application HTML?

Tags:

webpack

My webpack entry point includes a [hash] in the name:

entry: "index.js",
output: {
    path: "build/",
    filename: "index-[hash].js",
}

How can I link directly to that entry point from my application's HTML?

For example, I'd like the HTML that's sent to the client to include:

<script src="build/index-41d40fe7b20ba1dce81f.js"></script>

How can I do this? Is there a plugin which can generate an entry point manifest which my application can read and emit the appropriate file names?

like image 246
David Wolever Avatar asked Jul 03 '14 21:07

David Wolever


People also ask

How does HTML webpack plugin work?

The HtmlWebpackPlugin simplifies creation of HTML files to serve your webpack bundles. This is especially useful for webpack bundles that include a hash in the filename which changes every compilation.


2 Answers

The html-webpack-plugin (I'm the author) will generate an index.html for you referencing the correct hashed bundle filename.

var HtmlWebpackPlugin = require("html-webpack-plugin");
var webpackConfig = {
    entry: "index.js",
    output: {
        path: "build/",
        filename: "index-[hash].js",
    },
    plugins: [new HtmlWebpackPlugin()]
}

This will produce build/index.html that includes your bundle with a <script> tag.

like image 67
Charles Blaxland Avatar answered Sep 20 '22 03:09

Charles Blaxland


I've just started playing with webpack, and have found that gulp is a good fit for writing the newly-hashed js files to index.html. If you'd rather not use gulp, this discussion regarding doing something similar with a plugin might help a bit. Here's a gulpfile snippet that might help a bit as well:

var util = require('util');
var path = require('path');
var gulp = require('gulp');
var runSequence = require('run-sequence');
var rimraf = require('rimraf');
var gzip = require('gulp-gzip');
var notify = require('gulp-notify');
var gutil = require('gulp-util');
var webpack = require('webpack');
var webpackConfig = require('./client/webpack.config');
var through2 = require('through2');

gulp.task("webpack", function (cb) {
    webpack(webpackConfig, function (err, stats) {
        if (err) throw new gutil.PluginError("webpack", err);

        var jsFilename = stats.toJson().assetsByChunkName['app'];
        console.log('>>>>', jsFilename);
        // if source-maps are turned on, you'll get [ 'somefile.js', 'somefile.js.map' ]
        if (util.isArray(jsFilename)) {
            jsFilename = jsFilename.filter(function (filename) {
                return path.extname(filename).toLowerCase() === '.js'
            }).shift();
        }

        // write the hashed main.js to /dist/index.html
        gulp.src('./client/index.html')
            .on('error', handleErrors)
            .pipe(through2.obj(function (vinylFile, enc, tCb) {
                vinylFile.contents = new Buffer(String(vinylFile.contents)
                    .replace('main.js', jsFilename));
                this.push(vinylFile);
                tCb();
            }))
            .pipe(gulp.dest('./dist/'));

        cb();
    });
});

function handleErrors() {
    var args = Array.prototype.slice.call(arguments);
    notify.onError({ title: 'Error', message: '<%= error.message %>'}).apply(this, args);
    this.emit('end');
}

gulp.task('gzip-deploy', function () {
    return gulp.src('./dist/**/*')
        .on('error', handleErrors)
        .pipe(gzip())
        .pipe(gulp.dest('./dist/'));
});

gulp.task('clean', function (cb) {
    return rimraf('./dist', cb);
});

gulp.task('default', function (cb) {
    runSequence('clean', 'webpack', cb);
});

gulp.task('deploy', function (cb) {
    webpackConfig.plugins = webpackConfig.plugins = [
        new webpack.optimize.UglifyJsPlugin(),
        new webpack.DefinePlugin({
            "process.env": {
                NODE_ENV: JSON.stringify("production")
            }
        })
    ];
    webpackConfig.watch = false;
    webpackConfig.devtool = null;
    webpackConfig.output.filename = "main-[hash].js";

    runSequence('clean', 'webpack', 'gzip-deploy', cb);
});

Here's my webpack.config.js file as well for a bit of context:

var path = require('path');

module.exports = {
    context: __dirname,
    devtool: 'source-map',
    entry: {
        app: './main.js'
    },
    watch: true,
    output: {
        path: path.join(__dirname, "/../dist"),
        filename: "main.js"
    },
    module: {
        loaders: [
            { test: /\.js$/, loader: 'jsx-loader?harmony' },
            { test: /\.css$/, loader: "style-loader!css-loader" },
            { test: /\.less$/, loader: "style-loader!css-loader!less-loader" },
            { test: /\.png$/, loader: "url-loader?prefix=img/&limit=8192" },
            { test: /\.jpg$/, loader: "url-loader?prefix=img/&limit=8192" },
            { test: /\.gif$/, loader: "url-loader?prefix=img/&limit=8192" },
            { test: /\.woff$/, loader: "url-loader?prefix=font/&limit=8192" },
            { test: /\.eot$/, loader: "file-loader?prefix=font/" },
            { test: /\.ttf$/, loader: "file-loader?prefix=font/" },
            { test: /\.svg$/, loader: "file-loader?prefix=font/" }
        ]
    },
    resolve: {
        extensions: ['', '.js', '.json'],
        modulesDirectories: ['node_modules']
    },
    plugins: []
};
like image 26
Max Avatar answered Sep 20 '22 03:09

Max