Skip to content

Commit e040133

Browse files
authored
Leverage terser to mangle/compress the generated js messages (#1086)
This patch implements to leverage [terser](https://www.npmjs.com/package/terser) to mangle/compress the generated `.js` messages when `--debug` option not added. If debugging the message files, users can run `generate-messages:dev` to check with the original files, including: 1. Removing the prettier dependency. 2. Integrating terser minification with error handling for JavaScript files. 3. Using a conditional debug flag (isDebug) to determine whether to minify the code. 4. Don't remove the blank line in the generated files because it will be handled by `terser` now. Fix: #1085
1 parent a725c65 commit e040133

File tree

2 files changed

+32
-38
lines changed

2 files changed

+32
-38
lines changed

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
"rebuild": "npm run clean && node-gyp -j 16 rebuild",
1919
"rebuild:dev": "npm run clean && node-gyp -j 16 rebuild --debug",
2020
"generate-messages": "node scripts/generate_messages.js",
21-
"generate-messages:dev": "node scripts/generate_messages.js --debug",
21+
"generate-messages:dev": "node scripts/generate_messages.js --debug && npx --yes prettier --ignore-path --write generated/**/*.js",
2222
"generate-tsd-messages": "node scripts/generate_tsd.js",
23-
"clean": "node-gyp clean && npx rimraf@6.0.1 ./generated",
23+
"clean": "node-gyp clean && npx rimraf ./generated",
2424
"install": "npm run rebuild",
2525
"postinstall": "npm run generate-messages",
2626
"docs": "cd docs && make",
27-
"test": "nyc node --expose-gc ./scripts/run_test.js && npx tsd",
27+
"test": "nyc node --expose-gc ./scripts/run_test.js && tsd",
2828
"lint": "eslint && node ./scripts/cpplint.js",
29-
"format": "clang-format -i -style=file ./src/*.cpp ./src/*.hpp && prettier --write \"{lib,rosidl_gen,rostsd_gen,rosidl_parser,types,example,test,scripts,benchmark,rostsd_gen}/**/*.{js,md,ts}\" ./*.{js,md,ts}",
29+
"format": "clang-format -i -style=file ./src/*.cpp ./src/*.hpp && npx --yes prettier --write \"{lib,rosidl_gen,rostsd_gen,rosidl_parser,types,example,test,scripts,benchmark,rostsd_gen}/**/*.{js,md,ts}\" ./*.{js,md,ts}",
3030
"prepare": "husky",
3131
"coverage": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
3232
},
@@ -62,6 +62,7 @@
6262
"lint-staged": "^15.2.10",
6363
"mocha": "^11.0.2",
6464
"nyc": "^17.1.0",
65+
"rimraf": "^6.0.1",
6566
"sinon": "^19.0.2",
6667
"tree-kill": "^1.2.2",
6768
"tsd": "^0.31.2",
@@ -79,7 +80,7 @@
7980
"is-close": "^1.3.3",
8081
"json-bigint": "^1.0.0",
8182
"nan": "^2.22.0",
82-
"prettier": "^3.4.2",
83+
"terser": "^5.39.0",
8384
"walk": "^2.3.15"
8485
},
8586
"husky": {

rosidl_gen/idl_generator.js

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
'use strict';
1616

1717
const dot = require('dot');
18-
const prettier = require('prettier');
18+
const { minify } = require('terser');
1919
const fse = require('fs-extra');
2020
const path = require('path');
2121
const parser = require('../rosidl_parser/rosidl_parser.js');
@@ -29,10 +29,6 @@ const dots = dot.process({
2929
path: path.join(__dirname, '../rosidl_gen/templates'),
3030
});
3131

32-
function removeEmptyLines(str) {
33-
return str.replace(/^\s*\n/gm, '');
34-
}
35-
3632
/**
3733
* Output generated code to disk. Do not overwrite
3834
* an existing file. If file already exists do nothing.
@@ -41,11 +37,18 @@ function removeEmptyLines(str) {
4137
* @param {string} code
4238
*/
4339
async function writeGeneratedCode(dir, fileName, code) {
44-
if (fileName.endsWith('.js')) {
45-
code = await prettier.format(code, { parser: 'babel' });
40+
let result = null;
41+
if (!isDebug && fileName.endsWith('.js')) {
42+
try {
43+
result = await minify(code);
44+
} catch (error) {
45+
console.error(`Error minifying ${fileName}:`, error);
46+
result = null;
47+
}
4648
}
49+
4750
await fse.mkdirs(dir);
48-
await fse.writeFile(path.join(dir, fileName), code);
51+
await fse.writeFile(path.join(dir, fileName), result ? result.code : code);
4952
}
5053

5154
async function generateServiceJSStruct(
@@ -61,9 +64,7 @@ async function generateServiceJSStruct(
6164
'__' +
6265
serviceInfo.interfaceName +
6366
'.js';
64-
const generatedSrvCode = removeEmptyLines(
65-
dots.service({ serviceInfo: serviceInfo })
66-
);
67+
const generatedSrvCode = dots.service({ serviceInfo: serviceInfo });
6768

6869
// We are going to only generate the service JavaScript file if it meets one
6970
// of the followings:
@@ -84,9 +85,7 @@ async function generateServiceJSStruct(
8485

8586
async function generateServiceEventMsg(serviceInfo, dir) {
8687
const fileName = serviceInfo.interfaceName + '.msg';
87-
const generatedEvent = removeEmptyLines(
88-
dots.service_event({ serviceInfo: serviceInfo })
89-
);
88+
const generatedEvent = dots.service_event({ serviceInfo: serviceInfo });
9089

9190
return writeGeneratedCode(dir, fileName, generatedEvent).then(() => {
9291
serviceInfo.interfaceName += '_Event';
@@ -119,14 +118,12 @@ async function generateServiceEventJSStruct(msgInfo, dir) {
119118
// const AddTwoInts_RequestWrapper = require('../../generated/example_interfaces/example_interfaces__srv__AddTwoInts_Request.js');
120119
// const AddTwoInts_ResponseWrapper = require('../../generated/example_interfaces/example_interfaces__srv__AddTwoInts_Response.js');
121120
msgInfo.isServiceEvent = true;
122-
const generatedCode = removeEmptyLines(
123-
dots.message({
124-
messageInfo: msgInfo,
125-
spec: spec,
126-
json: JSON.stringify(spec, null, ' '),
127-
isDebug: isDebug,
128-
})
129-
);
121+
const generatedCode = dots.message({
122+
messageInfo: msgInfo,
123+
spec: spec,
124+
json: JSON.stringify(spec, null, ' '),
125+
isDebug: isDebug,
126+
});
130127

131128
return writeGeneratedCode(dir, eventFileName, generatedCode);
132129
}
@@ -149,14 +146,12 @@ function generateMessageJSStructFromSpec(messageInfo, dir, spec) {
149146
spec.msgName +
150147
'.js';
151148

152-
const generatedCode = removeEmptyLines(
153-
dots.message({
154-
messageInfo: messageInfo,
155-
spec: spec,
156-
json: JSON.stringify(spec, null, ' '),
157-
isDebug: isDebug,
158-
})
159-
);
149+
const generatedCode = dots.message({
150+
messageInfo: messageInfo,
151+
spec: spec,
152+
json: JSON.stringify(spec, null, ' '),
153+
isDebug: isDebug,
154+
});
160155
return writeGeneratedCode(dir, fileName, generatedCode);
161156
}
162157

@@ -291,9 +286,7 @@ async function generateActionJSStruct(actionInfo, dir) {
291286
'__' +
292287
actionInfo.interfaceName +
293288
'.js';
294-
const generatedCode = removeEmptyLines(
295-
dots.action({ actionInfo: actionInfo })
296-
);
289+
const generatedCode = dots.action({ actionInfo: actionInfo });
297290
dir = path.join(dir, actionInfo.pkgName);
298291
const action = writeGeneratedCode(dir, fileName, generatedCode);
299292

0 commit comments

Comments
 (0)