Repository: netlify/zip-it-and-ship-it
Pull request #559 (2021-06-28 09:31:36)

feat: add processDynamicNodeImports config property
**- Summary**

Puts processing of dynamic import expressions behind a `processDynamicNodeImports` configuration property, so that we can roll out the feature more gracefully.

**- Test plan**

Added new test and adjusted existing tests.

github-actions[bot]: ## ⏱ Benchmark results

*Comparing with 11e3486bc4f2ecf0f7ea6dd72b40432cd5e48306*

### largeDepsEsbuild: 10.6s
 ⬇️ **12.88% decrease** vs. 11e3486bc4f2ecf0f7ea6dd72b40432cd5e48306
```
^           13s                                                                                           
│           ┌──┐   12.5s   12.3s                                   12.1s                                  
│  11.7s    |  |    ┌──┐    ┌──┐   11.6s    12s            11.6s    ┌──┐   11.4s    12s    11.5s          
│ ──┌──┐────┼──┼────┼──┼────┼──┼────┌──┐────┌──┐────────────┌──┐────┼──┼────┌──┐────┌──┐────┌──┐──────────
│   |  |    |  |    |  |    |  |    |  |    |  |   10.3s    |  |    |  |    |  |    |  |    |  |   10.6s  
│   |  |    |  |    |  |    |  |    |  |    |  |    ┌──┐    |  |    |  |    |  |    |  |    |  |    ┌──┐  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
└───┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴──>
    T-12    T-11    T-10    T-9     T-8     T-7     T-6     T-5     T-4     T-3     T-2     T-1      T    
```
<details>
<summary>Legend</summary>

- T-30 (11e3486bc4f2ecf0f7ea6dd72b40432cd5e48306): 12s
- T-29 (c7b62ca7080b6a1bbe77483fde32e9bcde326855): 10.1s
- T-28 (d7bbd41934ed22e31e1c56d64c1c98f8b1cac86f): 11.4s
- T-27 (c733b46dd3470999d2c2e51d5cfc1e38c087839a): 12.2s
- T-26 (f29156ef5395795ad40e9df9556908b58aec6ae9): 13.1s
- T-25 (459ae63da849a1e0d4a271276e0333936c058e4a): 12.6s
- T-24 (3b2bee45e41518ab4c5695de581c2e6202e533b6): 12.9s
- T-23 (3fb86ef73475a197318baf522e16966d35fc485b): 10.9s
- T-22 (f49afa12e3df4054cbc9191446b2d6f19c5deea4): 10.8s
- T-21 (baf9dfb9661d508bf052802101c5078a3ae7b6e5): 12.4s
- T-20 (4768f2fa3afe71f00b62e543291677ed130c92f8): 12.4s
- T-19 (6495b80b9e5886189c7f20a150d8c2ed6cf082b5): 10.5s
- T-18 (9e47927ca83777dd42b27f31d5feb3096d3e8ced): 10.7s
- T-17 (e2ae5ca6d1f640f13789b83e7211fc6a78116958): 10.9s
- T-16 (508721c3c2e3af2d672da86172686aa2e4e0776c): 12.5s
- T-15 (790010f035f121286c189ac88cf49e5a51de7a1b): 10.6s
- T-14 (0dfcc70a334d09523dcb127e1812d0dbbda7481b): 12s
- T-13 (c4c746323af0ffa3706c6136675aebbac2af1e3d): 10.3s
- T-12 (f1363d24abeeeb11abaed0c564ca5ae8874a70ae): 11.7s
- T-11 (a5cef00715188d477ba69f033c16de00cea768c0): 13s
- T-10 (febeffcae56016e74348c4380fd5572edcbe84d0): 12.5s
- T-9 (991d9c3ab2e4e4da188024e3e005601ce9f14896): 12.3s
- T-8 (dd7dd81e5bf63586018d0ef384c399b2c1ba21c4): 11.6s
- T-7 (d4bcaf0ab1ab6f984d4658da105936a21011fe66): 12s
- T-6 (92f64a67160ac9eb0301ae738e38d258117f2b06): 10.3s
- T-5 (06bc4f69b05c96899a1efbd953c560219291b568): 11.6s
- T-4 (6c0e5f1059d5e672ea5ee6509150e0896030e745): 12.1s
- T-3 (e4c22192f1f66aae395b00fe8eaf4c886781d723): 11.4s
- T-2 (3ba92859e8fbf0f20abc46912284575c24e18124): 12s
- T-1 (5cdd4d23e88300d026f0152222136a35849c3b7f): 11.5s
- **T (current commit): 10.6s**</details>
### largeDepsZisi: 54.8s
 ⬇️ **14.75% decrease** vs. 11e3486bc4f2ecf0f7ea6dd72b40432cd5e48306
```
^         1m 9.5s                                                                                         
│           ┌──┐                          1m 7.1s         1m 4.4s                                         
│           |  |  1m 3.7s 1m 2.9s           ┌──┐            ┌──┐  1m 3.6s         1m 2.7s 1m 2.4s         
│ ─59.5s────┼──┼────┌──┐────┌──┐───59.5s────┼──┼────────────┼──┼────┌──┐───59.3s────┌──┐────┌──┐──────────
│   ┌──┐    |  |    |  |    |  |    ┌──┐    |  |   54.7s    |  |    |  |    ┌──┐    |  |    |  |   54.8s  
│   |  |    |  |    |  |    |  |    |  |    |  |    ┌──┐    |  |    |  |    |  |    |  |    |  |    ┌──┐  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
│   |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |  |    |▒▒|  
└───┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴────┴──┴──>
    T-12    T-11    T-10    T-9     T-8     T-7     T-6     T-5     T-4     T-3     T-2     T-1      T    
```
<details>
<summary>Legend</summary>

- T-30 (11e3486bc4f2ecf0f7ea6dd72b40432cd5e48306): 1m 2.9s
- T-29 (c7b62ca7080b6a1bbe77483fde32e9bcde326855): 53.4s
- T-28 (d7bbd41934ed22e31e1c56d64c1c98f8b1cac86f): 59.9s
- T-27 (c733b46dd3470999d2c2e51d5cfc1e38c087839a): 1m 3.5s
- T-26 (f29156ef5395795ad40e9df9556908b58aec6ae9): 1m 11.6s
- T-25 (459ae63da849a1e0d4a271276e0333936c058e4a): 1m 4.5s
- T-24 (3b2bee45e41518ab4c5695de581c2e6202e533b6): 1m 6.6s
- T-23 (3fb86ef73475a197318baf522e16966d35fc485b): 55.7s
- T-22 (f49afa12e3df4054cbc9191446b2d6f19c5deea4): 54.8s
- T-21 (baf9dfb9661d508bf052802101c5078a3ae7b6e5): 1m 4.8s
- T-20 (4768f2fa3afe71f00b62e543291677ed130c92f8): 1m 4.7s
- T-19 (6495b80b9e5886189c7f20a150d8c2ed6cf082b5): 54.5s
- T-18 (9e47927ca83777dd42b27f31d5feb3096d3e8ced): 54.6s
- T-17 (e2ae5ca6d1f640f13789b83e7211fc6a78116958): 55.4s
- T-16 (508721c3c2e3af2d672da86172686aa2e4e0776c): 1m 3.1s
- T-15 (790010f035f121286c189ac88cf49e5a51de7a1b): 54s
- T-14 (0dfcc70a334d09523dcb127e1812d0dbbda7481b): 1m 3.9s
- T-13 (c4c746323af0ffa3706c6136675aebbac2af1e3d): 54.3s
- T-12 (f1363d24abeeeb11abaed0c564ca5ae8874a70ae): 59.5s
- T-11 (a5cef00715188d477ba69f033c16de00cea768c0): 1m 9.5s
- T-10 (febeffcae56016e74348c4380fd5572edcbe84d0): 1m 3.7s
- T-9 (991d9c3ab2e4e4da188024e3e005601ce9f14896): 1m 2.9s
- T-8 (dd7dd81e5bf63586018d0ef384c399b2c1ba21c4): 59.5s
- T-7 (d4bcaf0ab1ab6f984d4658da105936a21011fe66): 1m 7.1s
- T-6 (92f64a67160ac9eb0301ae738e38d258117f2b06): 54.7s
- T-5 (06bc4f69b05c96899a1efbd953c560219291b568): 1m 4.4s
- T-4 (6c0e5f1059d5e672ea5ee6509150e0896030e745): 1m 3.6s
- T-3 (e4c22192f1f66aae395b00fe8eaf4c886781d723): 59.3s
- T-2 (3ba92859e8fbf0f20abc46912284575c24e18124): 1m 2.7s
- T-1 (5cdd4d23e88300d026f0152222136a35849c3b7f): 1m 2.4s
- **T (current commit): 54.8s**</details>
<!--delta:benchmark@{}-->

Patch:
diff --git a/src/runtimes/node/bundler.js b/src/runtimes/node/bundler.js
index 3905179..0e7a9b8 100644
--- a/src/runtimes/node/bundler.js
+++ b/src/runtimes/node/bundler.js
@@ -65,6 +65,7 @@ const bundleJsFile = async function ({
       basePath,
       includedPaths: dynamicImportsIncludedPaths,
       moduleNames: nodeModulesWithDynamicImports,
+      processImports: config.processDynamicNodeImports === true,
       srcDir,
     }),
   ]
diff --git a/src/runtimes/node/dynamic_imports/plugin.js b/src/runtimes/node/dynamic_imports/plugin.js
index 77c1d13..ceff3fe 100644
--- a/src/runtimes/node/dynamic_imports/plugin.js
+++ b/src/runtimes/node/dynamic_imports/plugin.js
@@ -13,11 +13,12 @@ const { parseExpression } = require('./parser')
 // issues. Secondly, it parses the dynamic expressions and tries to include in
 // the bundle all the files that are possibly needed to make the import work at
 // runtime. This is not always possible, but we do our best.
-const getDynamicImportsPlugin = ({ basePath, includedPaths, moduleNames, srcDir }) => ({
+const getDynamicImportsPlugin = ({ basePath, includedPaths, moduleNames, processImports, srcDir }) => ({
   name: 'dynamic-imports',
   setup(build) {
     const cache = new Map()
 
+    // eslint-disable-next-line complexity
     build.onDynamicImport({}, async (args) => {
       const { expression, resolveDir } = args
 
@@ -25,7 +26,9 @@ const getDynamicImportsPlugin = ({ basePath, includedPaths, moduleNames, srcDir
 
       // Don't attempt to parse the expression if the base path isn't defined,
       // since we won't be able to generate the globs for the included paths.
-      if (!basePath) {
+      // Also don't parse the expression if we're not interested in processing
+      // the dynamic import expressions.
+      if (!basePath || !processImports) {
         return
       }
 


Test patch:
diff --git a/tests/main.js b/tests/main.js
index 264c18b..289a235 100644
--- a/tests/main.js
+++ b/tests/main.js
@@ -1236,10 +1236,29 @@ test('Returns an empty list of modules with dynamic imports if the modules are m
   t.is(files[0].nodeModulesWithDynamicImports.length, 0)
 })
 
+test('Leaves dynamic imports untouched when the `processDynamicNodeImports` configuration property is not `true`', async (t) => {
+  const fixtureName = 'node-module-dynamic-import-template-literal'
+  const { tmpDir } = await zipNode(t, fixtureName, {
+    opts: { basePath: join(FIXTURES_DIR, fixtureName), config: { '*': { nodeBundler: ESBUILD } } },
+  })
+  const functionSource = await pReadFile(`${tmpDir}/src/function.js`, 'utf8')
+
+  /* eslint-disable no-template-curly-in-string */
+  t.true(functionSource.includes('const require1 = require(`./files/${number}.js`);'))
+  t.true(functionSource.includes('const require2 = require(`./files/${number}`);'))
+  t.true(functionSource.includes('const require3 = require(`./files/${parent.child}`);'))
+  t.true(functionSource.includes('const require4 = require(`./files/${arr[0]}`);'))
+  t.true(functionSource.includes('const require5 = require(`./files/${number.length > 0 ? number : "uh-oh"}`);'))
+  /* eslint-enable no-template-curly-in-string */
+})
+
 test('Adds a runtime shim and includes the files needed for dynamic imports using a template literal', async (t) => {
   const fixtureName = 'node-module-dynamic-import-template-literal'
   const { files, tmpDir } = await zipNode(t, fixtureName, {
-    opts: { basePath: join(FIXTURES_DIR, fixtureName), config: { '*': { nodeBundler: ESBUILD } } },
+    opts: {
+      basePath: join(FIXTURES_DIR, fixtureName),
+      config: { '*': { nodeBundler: ESBUILD, processDynamicNodeImports: true } },
+    },
   })
 
   // eslint-disable-next-line import/no-dynamic-require, node/global-require
@@ -1257,7 +1276,10 @@ test('Adds a runtime shim and includes the files needed for dynamic imports usin
 test('Leaves dynamic imports untouched when the files required to resolve the expression cannot be packaged at build time', async (t) => {
   const fixtureName = 'node-module-dynamic-import-unresolvable'
   const { tmpDir } = await zipNode(t, fixtureName, {
-    opts: { basePath: join(FIXTURES_DIR, fixtureName), config: { '*': { nodeBundler: ESBUILD } } },
+    opts: {
+      basePath: join(FIXTURES_DIR, fixtureName),
+      config: { '*': { nodeBundler: ESBUILD, processDynamicNodeImports: true } },
+    },
   })
   const functionSource = await pReadFile(`${tmpDir}/src/function.js`, 'utf8')
 
@@ -1270,7 +1292,10 @@ test('Leaves dynamic imports untouched when the files required to resolve the ex
 test('Adds a runtime shim and includes the files needed for dynamic imports using an expression built with the `+` operator', async (t) => {
   const fixtureName = 'node-module-dynamic-import-2'
   const { tmpDir } = await zipNode(t, fixtureName, {
-    opts: { basePath: join(FIXTURES_DIR, fixtureName), config: { '*': { nodeBundler: ESBUILD } } },
+    opts: {
+      basePath: join(FIXTURES_DIR, fixtureName),
+      config: { '*': { nodeBundler: ESBUILD, processDynamicNodeImports: true } },
+    },
   })
 
   // eslint-disable-next-line import/no-dynamic-require, node/global-require
@@ -1288,7 +1313,7 @@ test('Negated files in `included_files` are excluded from the bundle even if the
   const { tmpDir } = await zipNode(t, fixtureName, {
     opts: {
       basePath: join(FIXTURES_DIR, fixtureName),
-      config: { '*': { includedFiles: ['!lang/en.*'], nodeBundler: ESBUILD } },
+      config: { '*': { includedFiles: ['!lang/en.*'], nodeBundler: ESBUILD, processDynamicNodeImports: true } },
     },
   })
 
@@ -1306,7 +1331,10 @@ test('Creates dynamic import shims for functions with the same name and same shi
 
   const { tmpDir } = await zipNode(t, fixtureName, {
     length: FUNCTION_COUNT,
-    opts: { basePath: join(FIXTURES_DIR, fixtureName), config: { '*': { nodeBundler: ESBUILD } } },
+    opts: {
+      basePath: join(FIXTURES_DIR, fixtureName),
+      config: { '*': { nodeBundler: ESBUILD, processDynamicNodeImports: true } },
+    },
   })
 
   for (let ind = 1; ind <= FUNCTION_COUNT; ind++) {