Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lencioni/66fd086f868ff37ba4a27ae6ced7b0f3 to your computer and use it in GitHub Desktop.
Save lencioni/66fd086f868ff37ba4a27ae6ced7b0f3 to your computer and use it in GitHub Desktop.
dynamic-import-requires-webpack-chunkname ESLint rule
/**
* @fileoverview dynamicImport requires a leading comment with the webpackChunkName
* @author Kimberly Strauch
* @copyright 2018 Kimberly Strauch. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict';
const rule = require('../../../lib/rules/dynamic-import-requires-webpack-chunkname');
const RuleTester = require('eslint').RuleTester;
const ruleTester = new RuleTester();
const importReplacement = 'dynamicImport';
const options = [{ importReplacement }];
const noLeadingCommentError = `${importReplacement} requires a leading block comment in the form: /* webpackChunkName: "moduleChunkName" */`;
const commentFormattingError = `${importReplacement} requires the leading comment to be in the form: /* webpackChunkName: "moduleChunkName" */`;
const nonBlockCommentError = `${importReplacement} must use a /* foo */ style comment, not a // foo comment`;
const numberOfArgumentsError = `${importReplacement} requires exactly 1 argument`;
const nonStringArgumentError = `${importReplacement} requires a string literal argument`;
ruleTester.run('dynamic-import-requires-webpack-chunkname', rule, {
valid: [
{
code: `dynamicImport(
/* webpackChunkName: "someModule" */
'test'
)`,
options,
},
{
code: `dynamicImport(
/* webpackChunkName: "Some_Other_Module" */
'test'
)`,
options,
},
{
code: `dynamicImport(
/* webpackChunkName: "Some_Other_Module_123" */
'test'
)`,
options,
},
],
invalid: [
{
code: `dynamicImport(
/* webpackChunkName: "someModule" */
test
)`,
options,
errors: [{
message: nonStringArgumentError,
type: 'CallExpression',
}],
},
{
code: 'dynamicImport(someModule)',
options,
errors: [{
message: nonStringArgumentError,
type: 'CallExpression',
}],
},
{
code: `dynamicImport(
// webpackChunkName: "someModule"
'someModule'
)`,
options,
errors: [{
message: nonBlockCommentError,
type: 'CallExpression',
}],
},
{
code: `dynamicImport(
/* webpackChunkName: "someModule" */
test
)`,
options,
errors: [{
message: nonStringArgumentError,
type: 'CallExpression',
}],
},
{
code: 'dynamicImport()',
options,
errors: [{
message: numberOfArgumentsError,
type: 'CallExpression',
}],
},
{
code: `dynamicImport(
/* webpackChunkName: "someModule" */
)`,
options,
errors: [{
message: numberOfArgumentsError,
type: 'CallExpression',
}],
},
{
code: `dynamicImport(
/* webpackChunkName: "someModule" */
'someModule',
'someOtherModule'
)`,
options,
errors: [{
message: numberOfArgumentsError,
type: 'CallExpression',
}],
},
{
code: 'dynamicImport(\'test\')',
options,
errors: [{
message: noLeadingCommentError,
type: 'CallExpression',
}],
},
{
code: `dynamicImport(
/* webpackChunkName: someModule */
'someModule'
)`,
options,
errors: [{
message: commentFormattingError,
type: 'CallExpression',
}],
},
{
code: `dynamicImport(
/* webpackChunkName: 'someModule' */
'someModule'
)`,
options,
errors: [{
message: commentFormattingError,
type: 'CallExpression',
}],
},
{
code: `dynamicImport(
/* webpackChunkName "someModule" */
'someModule'
)`,
options,
errors: [{
message: commentFormattingError,
type: 'CallExpression',
}],
},
{
code: `dynamicImport(
/* webpackChunkName:"someModule" */
'someModule'
)`,
options,
errors: [{
message: commentFormattingError,
type: 'CallExpression',
}],
},
],
});
/**
* @fileoverview dynamic imports require a leading comment with the webpackChunkName
* @author Kimberly Strauch
* @copyright 2018 Kimberly Strauch. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict';
module.exports = {
meta: {
docs: {
description: 'Ensures correct usage of dynamic imports',
url: 'https://git.musta.ch/airbnb/eslint-plugin-airbnb/blob/master/docs/rules/dynamic-import-requires-webpack-chunkname.md',
},
schema: [{
type: 'object',
properties: {
importReplacement: {
type: 'string',
},
},
additionalProperties: false,
}],
},
create: function rule(context) {
const importFunction = context.options[0] ? context.options[0].importReplacement : 'import';
return {
[`CallExpression[callee.name="${importFunction}"]`](node) {
if (node.arguments.length !== 1) {
context.report(node, `${importFunction} requires exactly 1 argument`);
return;
}
const arg = node.arguments[0];
if (typeof arg.value !== 'string') {
context.report(node, `${importFunction} requires a string literal argument`);
return;
}
const sourceCode = context.getSourceCode();
const leadingComments = sourceCode.getComments(arg).leading;
if (!leadingComments || leadingComments.length !== 1) {
context.report(node, `${importFunction} requires a leading block comment in the form: /* webpackChunkName: "moduleChunkName" */`);
return;
}
if (leadingComments[0].type !== 'Block') {
context.report(node, `${importFunction} must use a /* foo */ style comment, not a // foo comment`);
return;
}
const webpackChunkDefinition = leadingComments[0].value;
const commentRegex = / webpackChunkName: "[a-zA-Z0-9-_/.]+" /;
if (!webpackChunkDefinition.match(commentRegex)) {
context.report(node, `${importFunction} requires the leading comment to be in the form: /* webpackChunkName: "moduleChunkName" */`);
}
},
};
},
};

dynamic imports require a leading comment with the webpackChunkName (dynamic-import-requires-webpack-chunkname)

Ensure proper usage of dynamic imports. It requires exactly one argument with a leading comment including the webpackChunkName so that webpack doesn't auto-generate the chunkname.

Rule Details

This rule can be configured with options to run against any import replacement function - in our case, dynamicImport.

{
  "dynamic-import-requires-webpack-chunkname": [2, { importReplacement: "dynamicImport" }]
}

The following patterns are considered warnings:

// no leading comment with chunkname
dynamicImport('someModule');

// leading comment, but two arguments
dynamicImport(
  /* webpackChunkName: "someModule" */
  'someModule',
  'someOtherModule'
);

// incorrectly formatted leading comment
dynamicImport(
  /*webpackChunkName:"someModule"*/
  'someModule',
);

// incorrectly formatted leading comment
dynamicImport(
  /* webpackChunkName: 'someModule' */
  'someModule',
);

// correctly formatted leading comment, argument is not a string
dynamicImport(
  /* webpackChunkName: "someModule" */
  someModule,
);

// using a single-line comment, not a block-style comment
dynamicImport(
  // webpackChunkName: "someModule"
  'someModule',
);

The following patterns are not warnings:

dynamicImport(
  /* webpackChunkName: "someModule" */
  'someModule',
);

dynamicImport(
  /* webpackChunkName: "Some_Other_Module" */
  'someOtherModule',
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment