Skip to content

Commit a655f36

Browse files
amsardesailjharb
authored andcommitted
[New] dynamic-import-chunkname: Allow empty chunk name when webpackMode: 'eager' is set; add suggestions to remove name in eager mode'
1 parent c0ac54b commit a655f36

File tree

5 files changed

+242
-9
lines changed

5 files changed

+242
-9
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
88

99
### Added
1010
- [`dynamic-import-chunkname`]: add `allowEmpty` option to allow empty leading comments ([#2942], thanks [@JiangWeixian])
11+
- [`dynamic-import-chunkname`]: Allow empty chunk name when webpackMode: 'eager' is set; add suggestions to remove name in eager mode ([#3004], thanks [@amsardesai])
1112

1213
### Changed
1314
- [Docs] `no-extraneous-dependencies`: Make glob pattern description more explicit ([#2944], thanks [@mulztob])
@@ -1115,6 +1116,7 @@ for info on changes for earlier releases.
11151116

11161117
[`memo-parser`]: ./memo-parser/README.md
11171118

1119+
[#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
11181120
[#2991]: https://github.com/import-js/eslint-plugin-import/pull/2991
11191121
[#2989]: https://github.com/import-js/eslint-plugin-import/pull/2989
11201122
[#2987]: https://github.com/import-js/eslint-plugin-import/pull/2987
@@ -1701,6 +1703,7 @@ for info on changes for earlier releases.
17011703
[@aladdin-add]: https://github.com/aladdin-add
17021704
[@alex-page]: https://github.com/alex-page
17031705
[@alexgorbatchev]: https://github.com/alexgorbatchev
1706+
[@amsardesai]: https://github.com/amsardesai
17041707
[@andreubotella]: https://github.com/andreubotella
17051708
[@AndrewLeedham]: https://github.com/AndrewLeedham
17061709
[@andyogo]: https://github.com/andyogo

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
7373
| Name                            | Description | 💼 | ⚠️ | 🚫 | 🔧 | 💡 ||
7474
| :------------------------------------------------------------------------------- | :------------------------------------------------------------------------- | :- | :---- | :- | :- | :- | :- |
7575
| [consistent-type-specifier-style](docs/rules/consistent-type-specifier-style.md) | Enforce or ban the use of inline type-only markers for named imports. | | | | 🔧 | | |
76-
| [dynamic-import-chunkname](docs/rules/dynamic-import-chunkname.md) | Enforce a leading comment with the webpackChunkName for dynamic imports. | | | | | | |
76+
| [dynamic-import-chunkname](docs/rules/dynamic-import-chunkname.md) | Enforce a leading comment with the webpackChunkName for dynamic imports. | | | | | 💡 | |
7777
| [exports-last](docs/rules/exports-last.md) | Ensure all exports appear after other statements. | | | | | | |
7878
| [extensions](docs/rules/extensions.md) | Ensure consistent use of file extension within the import path. | | | | | | |
7979
| [first](docs/rules/first.md) | Ensure all imports appear before other statements. | | | | 🔧 | | |

docs/rules/dynamic-import-chunkname.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# import/dynamic-import-chunkname
22

3+
💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
4+
35
<!-- end auto-generated rule header -->
46

57
This rule reports any dynamic imports without a webpackChunkName specified in a leading block comment in the proper format.
@@ -56,6 +58,13 @@ import(
5658
// webpackChunkName: "someModule"
5759
'someModule',
5860
);
61+
62+
// chunk names are disallowed when eager mode is set
63+
import(
64+
/* webpackMode: "eager" */
65+
/* webpackChunkName: "someModule" */
66+
'someModule',
67+
)
5968
```
6069

6170
### valid

src/rules/dynamic-import-chunkname.js

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module.exports = {
2727
},
2828
},
2929
}],
30+
hasSuggestions: true,
3031
},
3132

3233
create(context) {
@@ -36,8 +37,10 @@ module.exports = {
3637

3738
const paddedCommentRegex = /^ (\S[\s\S]+\S) $/;
3839
const commentStyleRegex = /^( ((webpackChunkName: .+)|((webpackPrefetch|webpackPreload): (true|false|-?[0-9]+))|(webpackIgnore: (true|false))|((webpackInclude|webpackExclude): \/.*\/)|(webpackMode: ["'](lazy|lazy-once|eager|weak)["'])|(webpackExports: (['"]\w+['"]|\[(['"]\w+['"], *)+(['"]\w+['"]*)\]))),?)+ $/;
39-
const chunkSubstrFormat = ` webpackChunkName: ["']${webpackChunknameFormat}["'],? `;
40+
const chunkSubstrFormat = `webpackChunkName: ["']${webpackChunknameFormat}["'],? `;
4041
const chunkSubstrRegex = new RegExp(chunkSubstrFormat);
42+
const eagerModeFormat = `webpackMode: ["']eager["'],? `;
43+
const eagerModeRegex = new RegExp(eagerModeFormat);
4144

4245
function run(node, arg) {
4346
const sourceCode = context.getSourceCode();
@@ -54,6 +57,7 @@ module.exports = {
5457
}
5558

5659
let isChunknamePresent = false;
60+
let isEagerModePresent = false;
5761

5862
for (const comment of leadingComments) {
5963
if (comment.type !== 'Block') {
@@ -92,12 +96,55 @@ module.exports = {
9296
return;
9397
}
9498

99+
if (eagerModeRegex.test(comment.value)) {
100+
isEagerModePresent = true;
101+
}
102+
95103
if (chunkSubstrRegex.test(comment.value)) {
96104
isChunknamePresent = true;
97105
}
98106
}
99107

100-
if (!isChunknamePresent && !allowEmpty) {
108+
if (isChunknamePresent && isEagerModePresent) {
109+
context.report({
110+
node,
111+
message: 'dynamic imports using eager mode do not need a webpackChunkName',
112+
suggest: [
113+
{
114+
desc: 'Remove webpackChunkName',
115+
fix(fixer) {
116+
for (const comment of leadingComments) {
117+
if (chunkSubstrRegex.test(comment.value)) {
118+
const replacement = comment.value.replace(chunkSubstrRegex, '').trim().replace(/,$/, '');
119+
if (replacement === '') {
120+
return fixer.remove(comment);
121+
} else {
122+
return fixer.replaceText(comment, `/* ${replacement} */`);
123+
}
124+
}
125+
}
126+
},
127+
},
128+
{
129+
desc: 'Remove webpackMode',
130+
fix(fixer) {
131+
for (const comment of leadingComments) {
132+
if (eagerModeRegex.test(comment.value)) {
133+
const replacement = comment.value.replace(eagerModeRegex, '').trim().replace(/,$/, '');
134+
if (replacement === '') {
135+
return fixer.remove(comment);
136+
} else {
137+
return fixer.replaceText(comment, `/* ${replacement} */`);
138+
}
139+
}
140+
}
141+
},
142+
},
143+
],
144+
});
145+
}
146+
147+
if (!isChunknamePresent && !allowEmpty && !isEagerModePresent) {
101148
context.report({
102149
node,
103150
message:

tests/src/rules/dynamic-import-chunkname.js

Lines changed: 180 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ const nonBlockCommentError = 'dynamic imports require a /* foo */ style comment,
2626
const noPaddingCommentError = 'dynamic imports require a block comment padded with spaces - /* foo */';
2727
const invalidSyntaxCommentError = 'dynamic imports require a "webpack" comment with valid syntax';
2828
const commentFormatError = `dynamic imports require a "webpack" comment with valid syntax`;
29-
const chunkNameFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${commentFormat}["'],? */`;
30-
const pickyChunkNameFormatError = `dynamic imports require a leading comment in the form /* webpackChunkName: ["']${pickyCommentFormat}["'],? */`;
29+
const chunkNameFormatError = `dynamic imports require a leading comment in the form /*webpackChunkName: ["']${commentFormat}["'],? */`;
30+
const pickyChunkNameFormatError = `dynamic imports require a leading comment in the form /*webpackChunkName: ["']${pickyCommentFormat}["'],? */`;
31+
const eagerModeError = `dynamic imports using eager mode do not need a webpackChunkName`;
3132

3233
ruleTester.run('dynamic-import-chunkname', rule, {
3334
valid: [
@@ -361,6 +362,14 @@ ruleTester.run('dynamic-import-chunkname', rule, {
361362
options,
362363
parser,
363364
},
365+
{
366+
code: `import(
367+
/* webpackMode: 'eager' */
368+
'someModule'
369+
)`,
370+
options,
371+
parser,
372+
},
364373
{
365374
code: `import(
366375
/* webpackChunkName: "someModule" */
@@ -412,7 +421,7 @@ ruleTester.run('dynamic-import-chunkname', rule, {
412421
/* webpackPrefetch: true */
413422
/* webpackPreload: true */
414423
/* webpackIgnore: false */
415-
/* webpackMode: "eager" */
424+
/* webpackMode: "lazy" */
416425
/* webpackExports: ["default", "named"] */
417426
'someModule'
418427
)`,
@@ -981,6 +990,24 @@ ruleTester.run('dynamic-import-chunkname', rule, {
981990
type: 'CallExpression',
982991
}],
983992
},
993+
{
994+
code: `import(
995+
/* webpackChunkName: "someModule" */
996+
/* webpackMode: "eager" */
997+
'someModule'
998+
)`,
999+
options,
1000+
parser,
1001+
output: `import(
1002+
/* webpackChunkName: "someModule" */
1003+
/* webpackMode: "eager" */
1004+
'someModule'
1005+
)`,
1006+
errors: [{
1007+
message: eagerModeError,
1008+
type: 'CallExpression',
1009+
}],
1010+
},
9841011
],
9851012
});
9861013

@@ -1216,11 +1243,38 @@ context('TypeScript', () => {
12161243
{
12171244
code: `import(
12181245
/* webpackChunkName: "someModule" */
1219-
/* webpackMode: "lazy" */
1246+
/* webpackMode: "eager" */
12201247
'someModule'
12211248
)`,
12221249
options,
12231250
parser: typescriptParser,
1251+
output: `import(
1252+
/* webpackChunkName: "someModule" */
1253+
/* webpackMode: "eager" */
1254+
'someModule'
1255+
)`,
1256+
errors: [{
1257+
message: eagerModeError,
1258+
type: nodeType,
1259+
suggestions: [
1260+
{
1261+
desc: 'Remove webpackChunkName',
1262+
output: `import(
1263+
1264+
/* webpackMode: "eager" */
1265+
'someModule'
1266+
)`,
1267+
},
1268+
{
1269+
desc: 'Remove webpackMode',
1270+
output: `import(
1271+
/* webpackChunkName: "someModule" */
1272+
1273+
'someModule'
1274+
)`,
1275+
},
1276+
],
1277+
}],
12241278
},
12251279
{
12261280
code: `import(
@@ -1242,7 +1296,7 @@ context('TypeScript', () => {
12421296
{
12431297
code: `import(
12441298
/* webpackChunkName: "someModule" */
1245-
/* webpackMode: "eager" */
1299+
/* webpackMode: "lazy" */
12461300
'someModule'
12471301
)`,
12481302
options,
@@ -1299,13 +1353,21 @@ context('TypeScript', () => {
12991353
/* webpackPrefetch: true */
13001354
/* webpackPreload: true */
13011355
/* webpackIgnore: false */
1302-
/* webpackMode: "eager" */
1356+
/* webpackMode: "lazy" */
13031357
/* webpackExports: ["default", "named"] */
13041358
'someModule'
13051359
)`,
13061360
options,
13071361
parser: typescriptParser,
13081362
},
1363+
{
1364+
code: `import(
1365+
/* webpackMode: 'eager' */
1366+
'someModule'
1367+
)`,
1368+
options,
1369+
parser: typescriptParser,
1370+
},
13091371
],
13101372
invalid: [
13111373
{
@@ -1752,6 +1814,118 @@ context('TypeScript', () => {
17521814
type: nodeType,
17531815
}],
17541816
},
1817+
{
1818+
code: `import(
1819+
/* webpackChunkName: "someModule", webpackMode: "eager" */
1820+
'someModule'
1821+
)`,
1822+
options,
1823+
parser: typescriptParser,
1824+
output: `import(
1825+
/* webpackChunkName: "someModule", webpackMode: "eager" */
1826+
'someModule'
1827+
)`,
1828+
errors: [{
1829+
message: eagerModeError,
1830+
type: nodeType,
1831+
suggestions: [
1832+
{
1833+
desc: 'Remove webpackChunkName',
1834+
output: `import(
1835+
/* webpackMode: "eager" */
1836+
'someModule'
1837+
)`,
1838+
},
1839+
{
1840+
desc: 'Remove webpackMode',
1841+
output: `import(
1842+
/* webpackChunkName: "someModule" */
1843+
'someModule'
1844+
)`,
1845+
},
1846+
],
1847+
}],
1848+
},
1849+
{
1850+
code: `
1851+
import(
1852+
/* webpackMode: "eager", webpackChunkName: "someModule" */
1853+
'someModule'
1854+
)
1855+
`,
1856+
options,
1857+
parser: typescriptParser,
1858+
output: `
1859+
import(
1860+
/* webpackMode: "eager", webpackChunkName: "someModule" */
1861+
'someModule'
1862+
)
1863+
`,
1864+
errors: [{
1865+
message: eagerModeError,
1866+
type: nodeType,
1867+
suggestions: [
1868+
{
1869+
desc: 'Remove webpackChunkName',
1870+
output: `
1871+
import(
1872+
/* webpackMode: "eager" */
1873+
'someModule'
1874+
)
1875+
`,
1876+
},
1877+
{
1878+
desc: 'Remove webpackMode',
1879+
output: `
1880+
import(
1881+
/* webpackChunkName: "someModule" */
1882+
'someModule'
1883+
)
1884+
`,
1885+
},
1886+
],
1887+
}],
1888+
},
1889+
{
1890+
code: `
1891+
import(
1892+
/* webpackMode: "eager", webpackPrefetch: true, webpackChunkName: "someModule" */
1893+
'someModule'
1894+
)
1895+
`,
1896+
options,
1897+
parser: typescriptParser,
1898+
output: `
1899+
import(
1900+
/* webpackMode: "eager", webpackPrefetch: true, webpackChunkName: "someModule" */
1901+
'someModule'
1902+
)
1903+
`,
1904+
errors: [{
1905+
message: eagerModeError,
1906+
type: nodeType,
1907+
suggestions: [
1908+
{
1909+
desc: 'Remove webpackChunkName',
1910+
output: `
1911+
import(
1912+
/* webpackMode: "eager", webpackPrefetch: true */
1913+
'someModule'
1914+
)
1915+
`,
1916+
},
1917+
{
1918+
desc: 'Remove webpackMode',
1919+
output: `
1920+
import(
1921+
/* webpackPrefetch: true, webpackChunkName: "someModule" */
1922+
'someModule'
1923+
)
1924+
`,
1925+
},
1926+
],
1927+
}],
1928+
},
17551929
],
17561930
});
17571931
});

0 commit comments

Comments
 (0)