我有三种不同的Webpack配置(client.webpack.js,server.webpack.js和vendor.webpack.js)vendor.webpack.js用于创建供应商捆绑包,因为它们很少更改且占用很多资源空间。我们使用DllPlugin
生成它,并通过DllReferencePlugin
在client.webpack.js中使用生成的manifest.json。
我想做的改进是将哈希添加到供应商文件中,例如我想创建vendor.348723.js,而不是vendor.js。这样做的原因是为了改善缓存。
棘手的部分是我们的应用程序是同构的,这意味着HTML的生成是由服务器(Node.js + React,server.webpack.js)在运行时完成的。在服务器内部,在JS文件中,我们创建模板,并且在某处有<script type='text/javascript' src='/vendor.js'></script>
。我的问题是,如何在其中注入vendor.SOMEHASH.js?
我尝试过并失败的事情:
扩展的API插件
Caching with Webpack, [hash] value inside index source code, using React.js
使用vendor.webpack.js中的ExtendedAPIPlugin,并在生成HTML模板时尝试使用__webpack_hash__
,例如<script type='text/javascript' src='/vendor.${__webpack_hash__}.js'></script>
由于我有两种不同的Webpack配置,并且我在vendor.webpack.js中生成哈希,因此服务器在生成HTML模板时无法识别它。
其他相关信息
我们不使用html-webpack-plugin-我认为它不适用,因为我们有一个同构的应用程序。 (Webpack - Best way to update HTML to include latest [hashed] bundles)
我浏览过的其他相关页面
Link css filename with hash to index.html after the Extract Text Plugin
vendor.webpack.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
name: 'vendor',
mode: 'development',
entry: [
'axios',
'babel-polyfill',
'material-ui',
'classnames',
'mixpanel-browser',
'ramda',
'react',
'react-dropzone-component',
'react-dom',
'react-ga',
'react-helmet',
'react-redux',
'react-router-dom',
'react-router-redux',
'redux',
'redux-thunk',
'redux-saga'
],
output: {
path: path.resolve(__dirname, '../client'),
filename: 'vendor.js',
library: 'vendor_[hash]'
},
plugins: [
new webpack.DllPlugin({
name: 'vendor_[hash]',
path: path.resolve(__dirname, '../client/manifest.json')
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
}),
new webpack.ExtendedAPIPlugin(),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
}
client.webpack.js
require('env2')('env.json')
const path = require('path')
const webpack = require('webpack')
const StatsPlugin = require('stats-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const merge = require('webpack-merge')
const baseConfig = require('./base.js')
module.exports = merge(baseConfig.moduleRules, {
name: 'client',
mode: 'development',
target: 'web',
// Good compromise between speed and quality, suitable for local development.
devtool: 'cheap-module-eval-source-map',
entry: [path.resolve(__dirname, '../app/index.js')],
output: {
filename: 'client.[chunkhash].js',
chunkFilename: 'client.[chunkhash].js',
path: path.resolve(__dirname, '../client'),
publicPath: '/'
},
watchOptions: {
poll: true
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style.css'
}),
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, '../client/manifest.json')
}),
new StatsPlugin('stats.json'),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development')
}
})
],
optimization: {
runtimeChunk: 'single'
}
})
server.webpack.js
const fs = require('fs')
const path = require('path')
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const merge = require('webpack-merge')
const baseConfig = require('./base.js')
const res = p => path.resolve(__dirname, p)
const modeModules = res('../node_modules')
const entry = res('../lib/routes/resources/reactUrls.js')
const output = res('../buildServer')
// if you're specifying externals to leave unbundled, you need to tell Webpack
// to still bundle `react-universal-component`, `webpack-flush-chunks` and
// `require-universal-module` so that they know they are running
// within Webpack and can properly make connections to client modules:
const externals = fs
.readdirSync(modeModules)
.filter(x => !/\.bin|react-universal-component|webpack-flush-chunks/.test(x))
.reduce((externals, mod) => {
externals[mod] = `commonjs ${mod}`
return externals
}, {})
externals['react-dom/server'] = 'commonjs react-dom/server'
module.exports = merge(baseConfig.commons, {
name: 'server',
mode: 'development',
target: 'node',
// Good compromise between speed and quality, suitable for local development.
devtool: 'cheap-module-eval-source-map',
entry: [entry],
externals,
output: {
path: output,
filename: '[name].js',
libraryTarget: 'commonjs2'
},
plugins: [
new MiniCssExtractPlugin({
filename: '/style.css'
}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
}),
new webpack.EnvironmentPlugin(['NODE_ENV'])
]
})