Skip to content

Commit dbf9ab9

Browse files
Safaa OugunirSafaa Ougunir
authored andcommitted
feat: add avoid using resource hungry libs
1 parent e4ce6f1 commit dbf9ab9

File tree

5 files changed

+267
-0
lines changed

5 files changed

+267
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- [#51](https://github.com/green-code-initiative/creedengo-javascript/pull/51) Add ESLint v9 and flat config support
13+
- [#90](https://github.com/green-code-initiative/creedengo-javascript/pull/90) Add avoid using resource-hungry libs rule
1314

1415
### Changed
1516

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Avoid using resource hungry libraries(`@creedengo/avoid-using-resource-hungry-libs`)
2+
3+
⚠️ This rule _warns_ in the following configs: ✅ `flat/recommended`, ✅ `recommended`.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
## Why is this an issue?
8+
9+
Avoid imports of known resource-hungry or deprecated libraries and suggest lighter alternatives.
10+
11+
This rule flags any import, require or dynamic import of libraries listed in the project’s deprecation dictionary (`moment`, `iconsax`, etc.), because these libraries
12+
1. Inflate your bundle size
13+
2. Slow parsing & compilation
14+
3. Often lack tree-shaking support
15+
4. May be unmaintained
16+
17+
```js
18+
import moment from "moment";
19+
const age = moment().diff(birthday, "years");
20+
```
21+
22+
```js
23+
import differenceInYears from "date-fns/differenceInYears";
24+
25+
const age = differenceInYears(new Date(), birthday);
26+
```
27+
28+
## Resources
29+
30+
### Documentation
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
3+
* Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
"use strict";
20+
21+
/**
22+
* List of deprecated libraries and their suggested replacements.
23+
*
24+
* Key = package name to forbid
25+
* Value = { reason: string, alternatives: string[] }
26+
*/
27+
const DEPRECATED_LIBS = {
28+
moment: {
29+
reason: "deprecated and heavy to load",
30+
alternatives: ["date-fns", "dayjs"],
31+
},
32+
iconsax: {
33+
reason: "does not support tree-shaking and adds large bundle size",
34+
alternatives: ["@mui/icons-material", "lucide-react"],
35+
},
36+
lodash: {
37+
reason: "too large, prefer modular imports or native methods",
38+
alternatives: ["lodash.get", "Array.prototype.map", "Object.assign"],
39+
},
40+
// add more entries here as needed
41+
};
42+
43+
module.exports = {
44+
meta: {
45+
type: "suggestion",
46+
docs: {
47+
description:
48+
"Disallow importing deprecated libraries and suggest lighter alternatives",
49+
category: "best-practice",
50+
recommended: "warn",
51+
},
52+
messages: {
53+
noDeprecatedLib:
54+
"Library '{{name}}' is {{reason}}. Consider using {{alternatives}}.",
55+
},
56+
schema: [],
57+
},
58+
59+
create(context) {
60+
/**
61+
* Report a deprecation warning on the given node.
62+
*/
63+
function reportDeprecation(node, libName) {
64+
const { reason, alternatives } = DEPRECATED_LIBS[libName];
65+
context.report({
66+
node,
67+
messageId: "noDeprecatedLib",
68+
data: {
69+
name: libName,
70+
reason,
71+
alternatives: alternatives.join(", "),
72+
},
73+
});
74+
}
75+
76+
return {
77+
// import moment from "moment";
78+
ImportDeclaration(node) {
79+
const pkg = node.source.value;
80+
if (DEPRECATED_LIBS[pkg]) {
81+
reportDeprecation(node.source, pkg);
82+
}
83+
},
84+
85+
// const moment = require("moment");
86+
CallExpression(node) {
87+
if (
88+
node.callee.type === "Identifier" &&
89+
node.callee.name === "require" &&
90+
node.arguments.length === 1
91+
) {
92+
const arg = node.arguments[0];
93+
if (
94+
arg.type === "Literal" &&
95+
typeof arg.value === "string" &&
96+
DEPRECATED_LIBS[arg.value]
97+
) {
98+
reportDeprecation(arg, arg.value);
99+
}
100+
}
101+
},
102+
103+
// import("moment").then(...)
104+
ImportExpression(node) {
105+
const src = node.source;
106+
if (src.type === "Literal" && DEPRECATED_LIBS[src.value]) {
107+
reportDeprecation(src, src.value);
108+
}
109+
},
110+
};
111+
},
112+
};
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
3+
* Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
"use strict";
20+
21+
//------------------------------------------------------------------------------
22+
// Requirements
23+
//------------------------------------------------------------------------------
24+
25+
const rule = require("../../../lib/rules/avoid-using-resource-hungry-libs");
26+
const { RuleTester } = require("eslint");
27+
28+
const ruleTester = new RuleTester({
29+
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
30+
});
31+
32+
const momentError = {
33+
messageId: "noDeprecatedLib",
34+
data: {
35+
name: "moment",
36+
reason: "deprecated and heavy to load",
37+
alternatives: "date-fns, dayjs",
38+
},
39+
type: "Literal",
40+
};
41+
42+
const iconsaxError = {
43+
messageId: "noDeprecatedLib",
44+
data: {
45+
name: "iconsax",
46+
reason: "does not support tree-shaking and adds large bundle size",
47+
alternatives: "@mui/icons-material, lucide-react",
48+
},
49+
type: "Literal",
50+
};
51+
52+
ruleTester.run("no-deprecated-libs", rule, {
53+
valid: [
54+
// imports of non-deprecated libraries
55+
`import dayjs from "dayjs";`,
56+
`const { format } = require("date-fns");`,
57+
`const moment = require("luxon");`,
58+
`import HomeIcon from "@mui/icons-material/Home";`,
59+
`import { ReactComponent as Icon } from "some-svg";`,
60+
`import("dayjs").then(d => console.log(d));`,
61+
// dynamic import of non-deprecated
62+
`import("lucide-react").then(l => console.log(l));`,
63+
],
64+
invalid: [
65+
// -- moment cases --
66+
{ code: `import moment from "moment";`, errors: [momentError] },
67+
{ code: `import { duration } from "moment";`, errors: [momentError] },
68+
{ code: `import "moment";`, errors: [momentError] },
69+
{ code: `const moment = require("moment");`, errors: [momentError] },
70+
{ code: `require("moment");`, errors: [momentError] },
71+
{
72+
code: `import("moment").then(m => console.log(m));`,
73+
errors: [momentError],
74+
},
75+
76+
// -- iconsax cases --
77+
{ code: `import iconsax from "iconsax";`, errors: [iconsaxError] },
78+
{ code: `import { IconHome } from "iconsax";`, errors: [iconsaxError] },
79+
{ code: `import "iconsax";`, errors: [iconsaxError] },
80+
{ code: `const iconsax = require("iconsax");`, errors: [iconsaxError] },
81+
{ code: `require("iconsax");`, errors: [iconsaxError] },
82+
{
83+
code: `import("iconsax").then(i => console.log(i));`,
84+
errors: [iconsaxError],
85+
},
86+
],
87+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs
3+
* Copyright © 2023 Green Code Initiative (https://green-code-initiative.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package org.greencodeinitiative.creedengo.javascript.checks;
19+
20+
import org.sonar.check.Rule;
21+
import org.sonar.plugins.javascript.api.EslintBasedCheck;
22+
import org.sonar.plugins.javascript.api.JavaScriptRule;
23+
import org.sonar.plugins.javascript.api.TypeScriptRule;
24+
25+
@JavaScriptRule
26+
@TypeScriptRule
27+
@Rule(key = AvoidUsingResourceHungryLibs.RULE_KEY)
28+
public class AvoidUsingResourceHungryLibs implements EslintBasedCheck {
29+
30+
public static final String RULE_KEY = "GCI36";
31+
32+
@Override
33+
public String eslintKey() {
34+
return "@creedengo/avoid-autoplay";
35+
}
36+
37+
}

0 commit comments

Comments
 (0)