目前,Webpack 的性能默认值为 244KiB(未压缩),如果设置process.env.CI = true
,则构建将失败并抱怨性能下降。
Razzle,没有任何添加,已经是 192KiB(未压缩),不包括任何 CSS(上面也包括 CSS)。
如果您在 CI 中运行它,对基础 Razzle 项目的任何合理添加基本上都会导致构建失败。
entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
client (248 KiB)
static/css/bundle.c91c1092.css
static/js/bundle.5bcffbdf.js
webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
core-js
polyfills 不要破坏 - assign, find, from, promise
react-autosuggest
CI=true npm run build
并观察它掉下来我认为未压缩时的包大小错误令人困惑,但如果构建成功,我们会显示压缩大小。 此外,244KiB 的未压缩 JavaScript 从来都不是性能下降的指标——人们应该使用性能监控和预算来了解什么时候会降低用户体验。
这里有几个选项:
webpack.performance
遇到同样的问题。 虽然我认为删除似乎有点伤害。 您可以根据需要使用razzle.config.js
进行配置。 也许你会这样做:
module.exports = {
// ...
modify(defaultConfig, { target, dev }, webpack) {
if (!dev) {
config.performance = Object.assign({}, {
maxAssetSize: 100000,
maxEntrypointSize: 300000,
hints: false
})
}
return config
}
}
你好! 所以这就是开源与我的日常工作和生活之间的交易,我有很多事情要管理,所以我使用 GitHub 机器人在这里和那里自动化一些事情。 这个特定的 GitHub 机器人将把它标记为陈旧,因为它有一段时间没有最近的活动。 如果几天内没有进一步的活动,它将关闭。 不要把这当成个人 - 说真的 - 这是一个完全自动化的操作。 如果这是一个错误,请发表评论、私信我、发送航母 pidgeon 或烟雾信号。
ProBot 由于不活动而自动关闭它。 如果这是一个错误,请大声喊叫,我们将重新打开它。
我也遇到过这个问题,并认为应该在未来的版本中对其进行审查。 我喜欢内置性能预算的姿态,但 52KiB 的限额相当小。
我同意,但我发现有问题的是performance.hints
设置会在文件完全压缩之前触发警告(如果在 CI 上,则会触发完全错误)。 在我的例子中,在 CI 上运行razzle build
如下所示:
$ razzle build
Creating an optimized production build...
Compiling client...
Starting type checking and linting service...
Using 1 worker with 2048MB memory limit
Treating warnings as errors because process.env.CI = true.
Most CI servers set it automatically.
Failed to compile.
asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
static/js/bundle.99af500d.js (634 KiB)
entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
client (634 KiB)
static/js/bundle.99af500d.js
error Command failed with exit code 1.
在我的本地机器上,它看起来像这样:
$ razzle build
Creating an optimized production build...
Compiling client...
Starting type checking and linting service...
Using 1 worker with 2048MB memory limit
Compiled client successfully.
Compiling server...
Compiled server successfully.
Compiled successfully.
File sizes after gzip:
181.77 KB build/static/js/bundle.99af500d.js
10.04 KB build/static/js/2.945fb472.chunk.js
4.87 KB build/static/js/3.c9f99c02.chunk.js
1.9 KB build/static/js/6.a430e3d3.chunk.js
1.74 KB build/static/js/4.ee533cb7.chunk.js
1.04 KB build/static/js/0.aec4785f.chunk.js
574 B build/static/js/5.11154537.chunk.js
✨ Done in 10.95s.
您可以看到最终构建远小于 webpack 的performance.hints
设置默认设置的 244KiB 限制。
我已将@rohidee的建议添加到我们的razzle.config.js
中,但我宁愿以一种更简洁的方式来解决这个问题。
仅供参考,您可以测试您的 CI 如何构建您的应用程序,但在构建命令之前添加env CI=true
,在我的情况下是: env CI=true yarn build
我也经历过@mrmartineau所说的。
我认为有一个默认的资产大小限制是一件好事; 它让您对您的入门捆绑包中包含的内容保持敏锐。
但是,我希望使用 CI 环境变量设置_with_ 和_without_ 相同的块。 我知道 CI 上的警告和错误之间存在差异,但我不明白为什么在本地构建而不是在 CI 中构建时会有更多的块。
我们可以重新打开这个问题吗? 根据 CI env 变量,我仍然会得到不同的包大小。 我尝试在这里查看默认配置,但没有发现任何感兴趣的内容。
我的解决方法是将 CI 构建脚本设置为CI=false yarn build
,因此生成的包与我通常在本地运行yarn build
时得到的包相同,而无需禁用包大小警告。
我通过以下方式解决了这个问题:
在这样做的过程中,我意识到期望 razzle 根据 gzip 文件大小计算这些提示并不是很合理。 这一切都是由 webpack 性能提示插件完成的,该插件在非 gzip 上运行。
https://webpack.js.org/configuration/performance/
我的 razzle.config.js:
const logger = require('razzle-dev-utils/logger')
module.exports = {
plugins: [
useRuntimePortEnvironmentVariable,
WebpackSplitChunksRazzlePlugin({
// include both initial and async imports for chunking, not just initial
chunks: 'all',
// default is 3
maxInitialRequests: Infinity,
// default is 30000
minSize: 0,
}),
WebpackPerformanceHintsRazzlePlugin({
// Use a custom assetFilter to not warn about big source maps or vendor bundle
assetFilter: function(assetFilename) {
const isSrcMap = /\.map$/.test(assetFilename)
const isVendorBundle = /vendor/.test(assetFilename)
return ! (isSrcMap || isVendorBundle)
}
}),
'typescript',
],
}
function NoopRazzlePlugin() {
return function NoopRazzlePluginFunc(config) {
return config
}
}
function WebpackPerformanceHintsRazzlePlugin(pluginOptions) {
return function WebpackPerformanceHintsRazzlePluginFunc(config) {
return {
...config,
performance: {
...config.performance,
assetFilter: function(assetFilename) {
const isSrcMap = /\.map$/.test(assetFilename)
const isVendorBundle = /vendor/.test(assetFilename)
return ! (isSrcMap || isVendorBundle)
}
}
}
}
}
/**
* Update config to use process.env.PORT provided at *runtime*, not build-time, which is the default behavior
*/
// https://github.com/jaredpalmer/razzle/issues/906#issuecomment-467046269
function useRuntimePortEnvironmentVariable(config, { target, dev }, webpack) {
const appConfig = Object.assign({}, config);
// <strong i="13">@BUG</strong>: Do not inline certain env vars; https://github.com/jaredpalmer/razzle/issues/356
if (target === 'node') {
const idx = appConfig.plugins.findIndex(plugin => plugin.constructor.name === 'DefinePlugin');
const { definitions } = appConfig.plugins[idx];
const newDefs = Object.assign({}, definitions);
delete newDefs['process.env.PORT'];
delete newDefs['process.env.HOST'];
delete newDefs['process.env.PUBLIC_PATH'];
appConfig.plugins = [].concat(appConfig.plugins);
appConfig.plugins[idx] = new webpack.DefinePlugin(newDefs)
}
return appConfig;
}
/**
* Razzle Plugin to split common libraries into a chunk named 'vendor'.
* The idea is that this bundle will change way less often than the src code
* of this app, so will mean less average download size because vendor can be cached.
* Taken from https://github.com/jaredpalmer/razzle/tree/master/examples/with-vendor-bundle
*/
function WebpackSplitChunksRazzlePlugin(pluginOptions={}) {
return function WebpackSplitChunksRazzlePluginFunc (razzleConfigBefore, { target, dev }, webpack) {
const config = Object.assign({}, razzleConfigBefore);
// Change the name of the server output file in production
if (target === 'web') {
// modify filenaming to account for multiple entry files
config.output.filename = dev
? 'static/js/[name].js'
: 'static/js/[name].[hash:8].js';
// I think these are the default that webpack sets
// https://webpack.js.org/plugins/split-chunks-plugin/#optimizationsplitchunks
const defaultSplitChunksConfig = {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
automaticNameMaxLength: 30,
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
config.optimization.splitChunks = {
...defaultSplitChunksConfig,
...config.optimization.splitChunks,
...pluginOptions,
}
}
return config;
}
}
对任何在这里绊倒的人的警告:无论出于何种原因,上面提出的使用useRuntimePortEnvironmentVariable
、 WebpackSplitChunksRazzlePlugin
和WebpackPerformanceHintsRazzlePlugin
的解决方案在开发模式下都可以很好地工作,但可能会破坏客户端在生产模式下渲染。
最有用的评论
我也经历过@mrmartineau所说的。
我认为有一个默认的资产大小限制是一件好事; 它让您对您的入门捆绑包中包含的内容保持敏锐。
但是,我希望使用 CI 环境变量设置_with_ 和_without_ 相同的块。 我知道 CI 上的警告和错误之间存在差异,但我不明白为什么在本地构建而不是在 CI 中构建时会有更多的块。