Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/source/upgrade-guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,18 @@ Finally, update your add-on file {file}`babel.config.js`.
+ const presets = ['@plone/razzle'];
```

### Replace `razzle-dev-utils` with `@plone/razzle-dev-utils`
```{versionchanged} Volto 19.0.0-alpha.28
```

`@plone/razzle-dev-utils` is a maintained fork of the original `razzle-dev-utils` package that contains Volto-specific fixes and patches.

To verify whether your project requires updates, search for any direct references to internal `razzle-dev-utils` modules:

```shell
grep -R "razzle-dev-utils" -n --exclude-dir=node_modules || true
```

### `pnpm` has been upgraded to version 10
```{versionchanged} Volto 19.0.0-alpha.7
```
Expand Down
29 changes: 29 additions & 0 deletions packages/volto-razzle-dev-utils/.release-it.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"plugins": {
"../scripts/prepublish.js": {}
},
"hooks": {
"after:bump": [
"pipx run towncrier build --draft --yes --version ${version} > .changelog.draft",
"pipx run towncrier build --yes --version ${version}"
],
"after:release": "rm .changelog.draft"
},
"npm": {
"publish": false
},
"git": {
"commitArgs": ["--no-verify"],
"changelog": "pipx run towncrier build --draft --yes --version 0.0.0",
"requireUpstream": false,
"requireCleanWorkingDir": false,
"commitMessage": "Release @plone/razzle-dev-utils ${version}",
"tagName": "plone-razzle-dev-utils-${version}",
"tagAnnotation": "Release @plone/razzle-dev-utils ${version}"
},
"github": {
"release": true,
"releaseName": "@plone/razzle-dev-utils ${version}",
"releaseNotes": "cat .changelog.draft"
}
}
9 changes: 9 additions & 0 deletions packages/volto-razzle-dev-utils/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @plone/razzle-dev-utils Release Notes

<!-- Do *NOT* add new change log entries to this file.
Instead create a file in the news directory.
For helpful instructions, see:
https://6.docs.plone.org/contributing/index.html#change-log-entry
-->

<!-- towncrier release notes start -->
182 changes: 182 additions & 0 deletions packages/volto-razzle-dev-utils/FileSizeReporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
'use strict';

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

var fs = require('fs');
var path = require('path');
var chalk = require('chalk');
var filesize = require('filesize');
var recursive = require('recursive-readdir');
var stripAnsi = require('strip-ansi');
var gzipSize = require('gzip-size').sync;

function canReadAsset(asset) {
return (
/\.(js|css|html|json)$/.test(asset) &&
!/service-worker\.js/.test(asset) &&
!/precache-manifest\.[0-9a-f]+\.js/.test(asset)
);
}

// Prints a detailed summary of build files.
function printFileSizesAfterBuild(
webpackStats,
previousSizeMap,
buildFolder,
maxBundleGzipSize,
maxChunkGzipSize,
) {
var root = previousSizeMap.root;
var sizes = previousSizeMap.sizes;
var assets = (webpackStats.stats || [webpackStats])
.map((stats) =>
stats
.toJson({ all: false, assets: true })
.assets.filter((asset) => canReadAsset(asset.name))
.map((asset) => {
var fileContents = fs.readFileSync(path.join(root, asset.name));
var size = gzipSize(fileContents);
var previousSize = sizes[removeFileNameHash(root, asset.name)];
var difference = getDifferenceLabel(size, previousSize);
return {
folder: path.join(
path.basename(buildFolder),
path.basename(root),
path.dirname(asset.name),
),
name: path.basename(asset.name),
size: size,
sizeLabel:
filesize(size) + (difference ? ' (' + difference + ')' : ''),
};
}),
)
.reduce((single, all) => all.concat(single), []);
assets.sort((a, b) => b.size - a.size);
var longestSizeLabelLength = Math.max.apply(
null,
assets.map((a) => stripAnsi(a.sizeLabel).length),
);
var suggestBundleSplitting = false;
assets.forEach((asset) => {
var sizeLabel = asset.sizeLabel;
var sizeLength = stripAnsi(sizeLabel).length;
if (sizeLength < longestSizeLabelLength) {
var rightPadding = ' '.repeat(longestSizeLabelLength - sizeLength);
sizeLabel += rightPadding;
}
var isMainBundle = asset.name.indexOf('main.') === 0;
var maxRecommendedSize = isMainBundle
? maxBundleGzipSize
: maxChunkGzipSize;
var isLarge = maxRecommendedSize && asset.size > maxRecommendedSize;
if (isLarge && path.extname(asset.name) === '.js') {
suggestBundleSplitting = true;
}
console.log(
' ' +
(isLarge ? chalk.yellow(sizeLabel) : sizeLabel) +
' ' +
chalk.dim(
asset.folder + (/[\/\\]$/.test(asset.folder) ? '' : path.sep),
) +
chalk.cyan(asset.name),
);
});
if (suggestBundleSplitting) {
console.log();
console.log(
chalk.yellow('The bundle size is significantly larger than recommended.'),
);
console.log(
chalk.yellow(
'Consider reducing it with code splitting: https://goo.gl/9VhYWB',
),
);
console.log(
chalk.yellow(
'You can also analyze the project dependencies: https://goo.gl/LeUzfb',
),
);
}
}

function removeFileNameHash(buildFolder, fileName) {
return fileName
.replace(buildFolder, '')
.replace(/\\/g, '/')
.replace(
/\/?(.*)(\.[0-9a-f]+)(\.chunk)?(\.js|\.css)/,
(match, p1, p2, p3, p4) => p1 + p4,
);
}

// Input: 1024, 2048
// Output: "(+1 KB)"
function getDifferenceLabel(currentSize, previousSize) {
var FIFTY_KILOBYTES = 1024 * 50;
var difference = currentSize - previousSize;
var fileSize = !Number.isNaN(difference) ? filesize(difference) : 0;
if (difference >= FIFTY_KILOBYTES) {
return chalk.red('+' + fileSize);
} else if (difference < FIFTY_KILOBYTES && difference > 0) {
return chalk.yellow('+' + fileSize);
} else if (difference < 0) {
return chalk.green(fileSize);
} else {
return '';
}
}

function measureFileSizesBeforeBuild(buildFolder) {
return new Promise((resolve) => {
recursive(buildFolder, (err, fileNames) => {
var sizes;
if (!err && fileNames) {
sizes = fileNames.filter(canReadAsset).reduce((memo, fileName) => {
var contents = fs.readFileSync(fileName);
var key = removeFileNameHash(buildFolder, fileName);
memo[key] = gzipSize(contents);
return memo;
}, {});
}
resolve({
root: buildFolder,
sizes: sizes || {},
});
});
});
}

function removeFilePrefix(buildFolder, fileName) {
return fileName.replace(buildFolder, '').replace(/\\/g, '/');
}

function getFileNamesAsStat(buildFolder) {
return new Promise((resolve) => {
recursive(buildFolder, (err, fileNames) => {
var filteredFileNames;
if (!err && fileNames) {
filteredFileNames = fileNames
.filter(canReadAsset)
.map((fileName) => removeFilePrefix(buildFolder, fileName));
}
resolve({
toJson: () => ({
assets: filteredFileNames.map((name) => ({ name: name })),
}),
});
});
});
}

module.exports = {
measureFileSizesBeforeBuild: measureFileSizesBeforeBuild,
printFileSizesAfterBuild: printFileSizesAfterBuild,
getFileNamesAsStat: getFileNamesAsStat,
};
82 changes: 82 additions & 0 deletions packages/volto-razzle-dev-utils/FriendlyErrorsPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

const chalk = require('chalk');
const clearConsole = require('react-dev-utils/clearConsole');
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
const logger = require('./logger');

let WEBPACK_COMPILING = false;
let WEBPACK_DONE = false;

// This is a custom Webpack Plugin that prints out prettier console messages
// and errors depending on webpack compiler events. It runs on the Node.js
// server webpack instance.
class WebpackErrorsPlugin {
constructor(options) {
options = options || {};
this.verbose = options.verbose;
this.onSuccessMessage = options.onSuccessMessage;
this.target = options.target === 'web' ? 'CLIENT' : 'SERVER';
}

apply(compiler) {
compiler.plugin('done', (stats) => {
const rawMessages = stats.toJson({}, true);
const messages = formatWebpackMessages(rawMessages);
WEBPACK_COMPILING = false;
if (!messages.errors.length && !messages.warnings.length) {
if (!WEBPACK_DONE) {
if (!this.verbose) {
clearConsole();
}
logger.done('Compiled successfully');
WEBPACK_DONE = true;

if (this.onSuccessMessage) {
logger.log(this.onSuccessMessage);
logger.log('');
}
}
}

if (
messages.errors.length &&
!(
rawMessages.errors &&
rawMessages.errors.length > 0 &&
(rawMessages.errors[0].includes('assets.json') ||
rawMessages.errors[0].includes('chunks.json') ||
rawMessages.errors[0].includes("Module not found: Can't resolve"))
)
) {
messages.errors.forEach((e) => {
logger.error(
`Failed to compile ${this.target} with ${messages.errors.length} errors`,
e,
);
});
// return;
}

if (messages.warnings.length) {
logger.warn(
`Failed to compile with ${messages.warnings.length} warnings`,
);
messages.warnings.forEach((w) => logger.log(w));
}
});

compiler.plugin('invalid', (params) => {
WEBPACK_DONE = false;
if (!WEBPACK_COMPILING) {
if (!this.verbose) {
clearConsole();
}
logger.start('Compiling...');
WEBPACK_COMPILING = true;
}
});
}
}

module.exports = WebpackErrorsPlugin;
Loading
Loading