webpack - 通过 Webpack 创建带有哈希的供应商包并在同构应用程序中使用它
问题描述
我有三种不同的 Webpack 配置(client.webpack.js、server.webpack.js 和 vendor.webpack.js) vendor.webpack.js 用于创建供应商包,因为它们很少更改并且占用大量空间。我们使用DllPlugin
它来生成它,并通过在 client.webpack.js 中使用生成的 manifest.json DllReferencePlugin
。
我想做的改进是向供应商文件添加一个哈希,例如,我想创建 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插件
使用 React.js 使用 Webpack 缓存,索引源代码中的 [hash] 值
在 vendor.webpack.js 中使用 ExtendedAPIPlugin,并尝试使用__webpack_hash__
在 vendor.webpack.js 中使用 ExtendedAPIPlugin,并在生成 HTML 模板时<script type='text/javascript' src='/vendor.${__webpack_hash__}.js'></script>
,例如,
由于我有两个不同的 Webpack 配置,并且我在 vendor.webpack.js 中生成哈希,服务器无法识别它生成 HTML 模板时。
其他相关信息
我们不使用 html-webpack-plugin——我认为它不适用,因为我们有一个同构的应用程序。( Webpack - 更新 HTML 以包含最新的 [hashed] 包的最佳方式)
我看过的其他相关页面
在提取文本插件之后将带有哈希的 css 文件名链接到 index.html
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$/)
]
}
客户端.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'])
]
})
解决方案
WebpackManifestPlugin可以用来解决这个问题。
推荐阅读
- visual-studio-code - 使用外部 http 服务器在 vscode 中构建代码
- delphi - 从 BDE 迁移到 ADO - 数据库
- jenkins-pipeline - Jenkins 脚本化管道 - 顺序步骤
- asp.net - 如何使 Web 浏览器的 url 保持在 MVC 错误 404 中
- vba - 使用添加的变量值重命名文件夹中的所有文件而不打开
- spring - 来自 yaml 的 Spring 配置 - 结合 @ConfigurationEnabled 加载参数化文件名
- android - 虚幻引擎如何处理手机不同的屏幕分辨率?特别是用户界面
- javascript - 向有页脚的表格添加滚动条
- php - Typo3 8.7.x / Typoscript:无法在表格页面中添加字段
- go - 以正确的方式选择协会