キャッシュバスターを強制するためにIonic v3でデフォルトのWebパック設定を拡張しました。
生成されたJavaScriptアーティファクトをフィンガープリントできますが、アセットフォルダーの下の画像とJSONファイルをフィンガープリントできません。 Bundled files and cache busting
からヘルプを取得しました。
webpack config.js
の抜粋
module.exports = {
// ...
output: {
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].js',
},
plugins: [
new WebpackChunkHash({algorithm: 'md5'}) // 'md5' is default value
]
}
上記はJavaScriptバンドルをフィンガープリントするためのアプローチであり、正常に機能しています。アセットフォルダー内にハッシュ/指紋画像とJSONファイルを追加したい。画像にも同じアプローチを使用しましたが、うまくいきませんでした。
Webpack config.jsを拡張し、画像の新しいルールを追加しました。デフォルトでは、webpackは画像とアセットを出力フォルダーに直接コピーします。
Config.jsをコピー
module.exports = {
copyAssets: {
src: ['{{SRC}}/assets/**/*'],
dest: '{{WWW}}/assets'
},
copyIndexContent: {
src: ['{{SRC}}/index.html', '{{SRC}}/manifest.json', '{{SRC}}/service-worker.js'],
dest: '{{WWW}}'
},
copyFonts: {
src: ['{{ROOT}}/node_modules/ionicons/dist/fonts/**/*', '{{ROOT}}/node_modules/ionic-angular/fonts/**/*'],
dest: '{{WWW}}/assets/fonts'
},
ここでは、画像やその他のアセットが直接コピーされます。拡張webpack.config.jsに新しいルールを追加しましたが、ビルドプロセスはそれを無視しています。この問題を修正するにはどうすればよいですか?
webpack config.js
の抜粋
{
test: /\.(png|jpg|gif)$/,
loader: 'file-loader',
options: {
name:'[name].[hash].[ext]',//adding hash for cache busting
outputPath:'assets/imgs',
publicPath:'assets/imgs'
},
webpack.config.js全体
/*
* The webpack config exports an object that has a valid webpack configuration
* For each environment name. By default, there are two Ionic environments:
* "dev" and "prod". As such, the webpack.config.js exports a dictionary object
* with "keys" for "dev" and "prod", where the value is a valid webpack configuration
* For details on configuring webpack, see their documentation here
* https://webpack.js.org/configuration/
*/
var path = require('path');
var webpack = require('webpack');
var ionicWebpackFactory = require(process.env.IONIC_WEBPACK_FACTORY);
var ModuleConcatPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');
var PurifyPlugin = require('@angular-devkit/build-optimizer').PurifyPlugin;
var optimizedProdLoaders = [
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.js$/,
loader: [
{
loader: process.env.IONIC_CACHE_LOADER
},
{
loader: '@angular-devkit/build-optimizer/webpack-loader',
options: {
sourceMap: true
}
},
]
},
{
test: /\.ts$/,
loader: [
{
loader: process.env.IONIC_CACHE_LOADER
},
{
loader: '@angular-devkit/build-optimizer/webpack-loader',
options: {
sourceMap: true
}
},
{
test: /\.(png|jpg|gif)$/,
loader: 'file-loader',
options: {
name:'[name].[hash].[ext]',
outputPath:'assets/imgs',
publicPath:'assets/imgs'
},
},
{
loader: process.env.IONIC_WEBPACK_LOADER
}
]
}
];
function getProdLoaders() {
if (process.env.IONIC_OPTIMIZE_JS === 'true') {
return optimizedProdLoaders;
}
return devConfig.module.loaders;
}
var devConfig = {
entry: process.env.IONIC_APP_ENTRY_POINT,
output: {
path: '{{BUILD}}',
publicPath: 'build/',
filename: '[name].js',
devtoolModuleFilenameTemplate: ionicWebpackFactory.getSourceMapperFunction(),
},
devtool: process.env.IONIC_SOURCE_MAP_TYPE,
resolve: {
extensions: ['.ts', '.js', '.json'],
modules: [path.resolve('node_modules')]
},
module: {
loaders: [
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.ts$/,
loader: process.env.IONIC_WEBPACK_LOADER
},
{
test: /\.(jpg|png)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[hash].[ext]",
outputPath:'assets/imgs',
publicPath:'assets/imgs'
},
}},
]
},
plugins: [
ionicWebpackFactory.getIonicEnvironmentPlugin(),
ionicWebpackFactory.getCommonChunksPlugin()
],
// Some libraries import Node.js modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
}
};
var prodConfig = {
entry: process.env.IONIC_APP_ENTRY_POINT,
output: {
path: '{{BUILD}}',
publicPath: 'build/',
filename: '[name].js',
devtoolModuleFilenameTemplate: ionicWebpackFactory.getSourceMapperFunction(),
},
devtool: process.env.IONIC_SOURCE_MAP_TYPE,
resolve: {
extensions: ['.ts', '.js', '.json'],
modules: [path.resolve('node_modules')]
},
module: {
loaders: getProdLoaders()
},
plugins: [
ionicWebpackFactory.getIonicEnvironmentPlugin(),
ionicWebpackFactory.getCommonChunksPlugin(),
new ModuleConcatPlugin(),
new PurifyPlugin()
],
// Some libraries import Node.js modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
}
};
module.exports = {
dev: devConfig,
prod: prodConfig
}
Webpack 4を使用すると、追加のプラグインやローダーは必要ありません。
命名オプション[contenthash]が提供されます。
また、このブロックはテストの下にネストされているように見えます:.tsブロック。
{
test: /\.(png|jpg|gif)$/,
loader: 'file-loader',
options: {
name:'[name].[hash].[ext]', // Adding hash for cache busting
outputPath:'assets/imgs',
publicPath:'assets/imgs'
},
最終的に、次のようなことができます。
// Copy static assets over with file-loader
{
test: /\.(ico)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader', options: {name: '[name].[contenthash].[ext]'},
},
{
test: /\.(woff|woff2|eot|ttf|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader', options: {name: 'fonts/[name].[contenthash].[ext]'},
},
{
test: /\.(jpg|gif|png|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader', options: {name: 'images/[name].[contenthash].[ext]'},
}
]
コンテンツの代わりに[chunkhash]を使用しても動作するはずです。webpack4を使用していない場合はそれを実行しますが、詳細については this issue を参照してください。
詳細については、 Googleの長期キャッシュパフォーマンスガイド および最新のキャッシュドキュメントを Webpack からお読みください。
webpack-assets-manifest
次のように、アセット名とフィンガープリントされた名前のマップを生成できます。
{
"images/logo.svg": "images/logo-b111da4f34cefce092b965ebc1078ee3.svg"
}
このマニフェストを使用して、宛先フォルダーのアセットの名前を変更し、プロジェクトで「正しい」ハッシュを含むsrcまたはhrefを使用できます。
修正はフレームワーク固有ではありません。
copyPluginを介してコピーされたファイルはローダーに渡されません。したがって、画像のハッシュ名を使用して正しいローダー設定を行っても、機能しません。
しかし、あなたは見ることができます https://github.com/webpack-contrib/copy-webpack-plugin#template
copyPluginは、ハッシュで設定できる出力名を指定する方法を提供します。
module.exports = {
plugins: [
new CopyPlugin([
{
from: 'src/',
to: 'dest/[name].[hash].[ext]',
toType: 'template',
},
]),
],
};