让 Webpack 将生成的哈希值输出到配置文件

Get Webpack to output the generated hash to a config file

这是我们项目使用的技术栈:

我们有一个问题,我们的 app.min.js 文件被缓存了,当我们进行需要新 app.min.js 文件的更改时,我们的客户通常会继续使用缓存文件而不是加载新文件,并且最终产生错误并不得不致电我们的支持台。

我研究了通过将文件内容的哈希值嵌入到 HTTP 请求中来解决此问题,然后让服务器使用重写规则提供原始文件。我已经将 [contenthash]. 添加到 webpack.config.js 中的文件名(见下文)但是当我 运行 Webpack 时,它不会替换 [contenthash],而是创建一个具有该确切内容的文件名字.

module.exports = {
    output: {
        filename: 'app.min.[contenthash].js'
    }
}

我希望发生的事情是:

  1. 输出文件仍称为 app.min.jsapp.min.js.map
  2. 生成的地图文件 app.min.js.map 链接到 app.min.6b1900549fed191ccbe8.js
  3. Webpack 将哈希值保存在配置文件的某处
    app_min_js_hash: '6b1900549fed191ccbe8'
    
  4. 我更改了 Twig 模板以包含如下哈希:
    <script src="/dist/js/app.min.{{ app_min_js_hash }}.js"></script>
    

所以我还有几个问题没有解决:

  1. 如何让 Webpack 将哈希输出到配置文件
  2. 如何让Webpack用hash替换关键字
  3. 如何让 Webpack 创建没有哈希的文件名

我已经知道如何解决 rewrite 和 Twig 部分了。


根据链接问题 () 中的评论,我现在得到:

webpack.config.js

var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackMajorVersion = require('webpack/package.json').version.split('.')[0];

module.exports = {
    console: true,
    name: 'js',
    entry: ['./src/base.js'],
    output: {
        path: '../web/dist/js/',
        publicPath: '/dist/js/',
        filename: 'app.min.[hash].js'
    },
    devtool: "source-map",
    resolve : {
        root : [path.join(__dirname, "src/")]
    },
    sassLoader: {
        includePaths: './src/'
    },
    resolveLoader: {
        root: __dirname+'/node_modules/',
        modulesDirectories: [""]
    },
    jshint: {
      esversion: 6
    },
    // Initialize module
    preLoaders: [],
    module: {
        preLoaders: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'jshint-loader',
            }
        ],
        loaders: [{
            // JS LOADER
            // Reference: https://github.com/babel/babel-loader
            // Transpile .js files using babel-loader
            // Compiles ES6 and ES7 into ES5 code
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            loader: 'babel',
            query: {
                presets: ['es2015']
            },
            exclude: /node_modules/
        }, {
            // ASSET LOADER
            // Reference: https://github.com/webpack/file-loader
            // Copy png, jpg, jpeg, gif, svg, woff, woff2, ttf, eot files to output
            // Rename the file using the asset hash
            // Pass along the updated reference to your code
            // You can add here any file extension you want to get copied to your output
            test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
            loader: 'file'
        }, {
            // HTML LOADER
            // Reference: https://github.com/webpack/raw-loader
            // Allow loading html through js
            test: /\.html$/,
            loader: "ngtemplate?relativeTo=" + (path.resolve(__dirname, './src/')) + "/!html"
        }, {
            test: /\.scss$/,
            loaders: ["style", "css", "sass"]
        }],
        resolve: {
            // you can now require('file') instead of require('file.coffee')
            extensions: ['', '.js', '.json', '.coffee']
        }
    },
    plugins: [
        new HtmlWebpackPlugin({
            templateContent: function(params) {
                return `
    {% block jsAssets %}
      ${params.htmlWebpackPlugin.files.js.map(
                  file => `<script src="${file}"></script>`,
                )}
    {% endblock %}

    {% block cssAssets %}
      ${params.htmlWebpackPlugin.files.css.map(
                  file => `<link rel="stylesheet" type="text/css" href="${file}">`,
                )}
    {% endblock %}`;
            },
            filename: '../../resources/templates/assets.html.twig',
            inject: false,
            // // The following settings are optional and only used for
            // // demo purposes:
            // meta: {
            //     charset: { charset: 'utf-8' },
            //     viewport: 'width=device-width, initial-scale=1'
            // },
            // minify: false
        })
    ]
};

在 Twig 代码 {{ block("jsAssets", "assets.html.twig") }} 执行任何操作之前 use 生成的 Twig 模板是必要的。

树枝:

{% use 'HTMLBundle:Layout:assets.html.twig' %}
...
{{ block("jsAssets", "assets.html.twig") }}
...

所以现在剩下的唯一问题是如何每次都保持输出文件名相同,同时仍然生成散列。否则,该目录将不断填满不同的散列版本(不是很小)。只需要最新的文件。我们使用一步部署,因此每次生成文件时都必须手动重命名文件,这打破了这种模式。


† 我已经知道这个版本太旧了。短期内不会改变。

在 webpack 1 中它被称为 [hash]。你不需要发明轮子。

HTMLWebpack 插件开箱即用,支持将散列注入 html(甚至 php 模板)

编辑:

您可以使用哈希作为查询字符串:

module.exports = {
    console: true,
    name: 'js',
    entry: ['./src/base.js'],
    output: {
        path: '../web/dist/js/',
        publicPath: '/dist/js/',
        filename: 'app.min.js?[hash]'
    },
}

或者您可以在自己的模板中的 js 文件名中添加散列。


new HtmlWebpackPlugin({
  templateContent: function(params) {
    return `
      {% block jsAssets %}
      ${params.htmlWebpackPlugin.files.js.map(
        file => {
          const [filename, hash] = file.split('?');
          const modifiedFileName = filename.replace('.min.js', 
          `${hash}.min.js`);
          return `<script src="${modifiedFileName}"></script>`
        }
     )}
     {% endblock %}
     `
}),