Вот стек технологий, который использует наш проект:
- Symfony 2.8†
- Ветка 1.24†
- AngularJS 1.5†
- Веб-пакет 1.12†
У нас есть проблема, заключающаяся в том, что наш файл app.min.js
кэшируется, и когда мы вносим изменения, для которых требуется новый файл app.min.js
, часто наши клиенты продолжают использовать кэшированный файл вместо загрузки нового файла, что в конечном итоге приводит к ошибкам и необходимости звонить в нашу службу поддержки.
Я попытался исправить это, внедрив хэш содержимого файла в HTTP-запрос, а затем заставив сервер обслуживать исходный файл с использованием правила перезаписи. Я добавил [contenthash].
к имени файла в webpack.config.js
(см. ниже), но когда я запускаю Webpack, он не заменяет [contenthash]
вместо создания файла с таким же именем.
module.exports = {
output: {
filename: 'app.min.[contenthash].js'
}
}
Я бы хотел, чтобы это произошло:
- выходные файлы по-прежнему называются
app.min.js
иapp.min.js.map
- сгенерированный файл карты
app.min.js.map
ссылается наapp.min.6b1900549fed191ccbe8.js
- Webpack сохраняет хэш где-то в конфигурационном файле
app_min_js_hash: '6b1900549fed191ccbe8'
- Я изменяю шаблоны Twig, чтобы включить хеш, как показано ниже:
<script src="/dist/js/app.min.{{ app_min_js_hash }}.js"></script>
Итак, у меня есть несколько проблем, которые я не решил:
Как заставить Webpack выводить хэш в файл конфигурацииКак заставить Webpack заменить ключевое слово хешем- Как заставить Webpack создавать имена файлов без хэша
Я уже знаю, как решить части rewrite и Twig.
Следуя комментариям в связанном вопросе (Загрузите пакет HtmlWebpackPlugin.[hash].js/css в базовый файл ветки), теперь у меня есть:
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
})
]
};
Необходимо use
сгенерированный шаблон Twig, прежде чем код Twig {{ block("jsAssets", "assets.html.twig") }}
что-то сделает.
Ветка:
{% use 'HTMLBundle:Layout:assets.html.twig' %}
...
{{ block("jsAssets", "assets.html.twig") }}
...
Итак, теперь единственная оставшаяся проблема заключается в том, как сохранить имя выходного файла одинаковым каждый раз, при этом генерируя хэш. В противном случае каталог будет продолжать заполняться различными хешированными версиями (которые не совсем маленькие). Всегда нужен только последний файл. Мы используем одноэтапное развертывание, поэтому необходимость вручную переименовывать файл каждый раз, когда он создается, нарушает эту парадигму.
† Я уже знаю, что эта версия слишком старая. В краткосрочной перспективе это не изменится.