<p dir="auto">I have a monorepo, containing a <code class="notranslate">create-react-app</code> application, a <code class="notranslate">next.js</code> application and a separate library. This library is linked (with <code class="notranslate">yarn link</code>) to the two applications and has <code class="notranslate">styled-components</code> as a peer dependency, which is installed in both the applications.</p>
<p dir="auto">The linking works fine in the <code class="notranslate">create-react-app</code> application but in <code class="notranslate">next.js</code> it breaks resulting in the following error:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Error in @scrnhq/eurovision-elements
Module not found: Error: Can't resolve 'styled-components' in '/Users/robert/sites/eurovision/elements/dist'
ModuleNotFoundError: Module not found: Error: Can't resolve 'styled-components' in '/Users/robert/sites/eurovision/elements/dist'
    at factoryCallback (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/Compilation.js:276:40)
    at factory (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/NormalModuleFactory.js:235:20)
    at resolver (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/NormalModuleFactory.js:60:20)
    at asyncLib.parallel (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/NormalModuleFactory.js:127:20)
    at /Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:3874:9
    at /Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:473:16
    at iteratorCallback (/Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:1048:13)
    at /Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:958:16
    at /Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:3871:13
    at resolvers.normal.resolve (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/NormalModuleFactory.js:119:22)
    at onError (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/Resolver.js:65:10)
    at loggingCallbackWrapper (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/createInnerCallback.js:31:19)
    at runAfter (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/Resolver.js:158:4)
    at innerCallback (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/Resolver.js:146:3)
    at loggingCallbackWrapper (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/createInnerCallback.js:31:19)
    at next (/Users/robert/sites/eurovision/pulse/node_modules/tapable/lib/Tapable.js:252:11)"><pre class="notranslate"><code class="notranslate">Error in @scrnhq/eurovision-elements
Module not found: Error: Can't resolve 'styled-components' in '/Users/robert/sites/eurovision/elements/dist'
ModuleNotFoundError: Module not found: Error: Can't resolve 'styled-components' in '/Users/robert/sites/eurovision/elements/dist'
    at factoryCallback (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/Compilation.js:276:40)
    at factory (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/NormalModuleFactory.js:235:20)
    at resolver (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/NormalModuleFactory.js:60:20)
    at asyncLib.parallel (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/NormalModuleFactory.js:127:20)
    at /Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:3874:9
    at /Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:473:16
    at iteratorCallback (/Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:1048:13)
    at /Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:958:16
    at /Users/robert/sites/eurovision/pulse/node_modules/async/dist/async.js:3871:13
    at resolvers.normal.resolve (/Users/robert/sites/eurovision/pulse/node_modules/webpack/lib/NormalModuleFactory.js:119:22)
    at onError (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/Resolver.js:65:10)
    at loggingCallbackWrapper (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/createInnerCallback.js:31:19)
    at runAfter (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/Resolver.js:158:4)
    at innerCallback (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/Resolver.js:146:3)
    at loggingCallbackWrapper (/Users/robert/sites/eurovision/pulse/node_modules/enhanced-resolve/lib/createInnerCallback.js:31:19)
    at next (/Users/robert/sites/eurovision/pulse/node_modules/tapable/lib/Tapable.js:252:11)
</code></pre></div>
<p dir="auto">Installing <code class="notranslate">styled-components</code> inside this library is not possible as it has to be a peer dependency, see: <a href="https://www.styled-components.com/docs/faqs#i-am-a-library-author-should-i-bundle-styledcomponents-with-my-library" rel="nofollow">https://www.styled-components.com/docs/faqs#i-am-a-library-author-should-i-bundle-styledcomponents-with-my-library</a></p>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the <a href="https://github.com/zeit/next.js/issues?q=is%3Aissue">issues</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<h2 dir="auto">Expected Behavior</h2>
<p dir="auto"><code class="notranslate">next.js</code> should resolve peer dependencies of linked modules in the correct way, meaning from the project's <code class="notranslate">node_modules</code> folder.</p>
<h2 dir="auto">Current Behavior</h2>
<p dir="auto">It looks like peer dependencies currently are not resolved from the correct place, as it looks like it's only looking at the folder (and parents) of the linked module itself.</p>
<h2 dir="auto">Steps to Reproduce (for bugs)</h2>
<p dir="auto">As this is a closed source project I can't share the source code or set up, but if necessary I can add a similar reproducible example later.</p>
<h2 dir="auto">Your Environment</h2>

<table role="table">
<thead>
<tr>
<th>Tech</th>
<th>Version</th>
</tr>
</thead>
<tbody>
<tr>
<td>next</td>
<td>5.1.0</td>
</tr>
<tr>
<td>node</td>
<td>9.6.1</td>
</tr>
<tr>
<td>OS</td>
<td>10.13.2</td>
</tr>
</tbody>
</table>
<p dir="auto">The <code class="notranslate">next/dynamic</code> import is failing in <a href="https://github.com/zeit/next.js/blob/master/server/build/babel/plugins/handle-import.js#L43">handle-import.js</a> due to a preprocessed module name evaluating to <code class="notranslate">undefined</code>. Boiled down version of code:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// index.js
const preval_modulename = preval`
    module.exports = './hello-' + 'world';
`;

console.log(preval_modulename); // prints './hello-world'
const DynamicComponent = dynamic(import(preval_modulename)); // reduces to import(undefined)

// .babelrc
{
    &quot;presets&quot;: [
        &quot;next/babel&quot;
    ],
    &quot;plugins&quot;: [
        &quot;preval&quot;
    ]
}"><pre class="notranslate"><span class="pl-c">// index.js</span>
<span class="pl-k">const</span> <span class="pl-s1">preval_modulename</span> <span class="pl-c1">=</span> <span class="pl-en">preval</span><span class="pl-s">`</span>
<span class="pl-s">    module.exports = './hello-' + 'world';</span>
<span class="pl-s">`</span><span class="pl-kos">;</span>

<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">preval_modulename</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// prints './hello-world'</span>
<span class="pl-k">const</span> <span class="pl-v">DynamicComponent</span> <span class="pl-c1">=</span> <span class="pl-en">dynamic</span><span class="pl-kos">(</span><span class="pl-k">import</span><span class="pl-kos">(</span><span class="pl-s1">preval_modulename</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// reduces to import(undefined)</span>

<span class="pl-c">// .babelrc</span>
<span class="pl-kos">{</span>
    <span class="pl-s">"presets"</span>: <span class="pl-kos">[</span>
        <span class="pl-s">"next/babel"</span>
    <span class="pl-kos">]</span><span class="pl-kos">,</span>
    <span class="pl-s">"plugins"</span>: <span class="pl-kos">[</span>
        <span class="pl-s">"preval"</span>
    <span class="pl-kos">]</span>
<span class="pl-kos">}</span></pre></div>


<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the <a href="https://github.com/zeit/next.js/issues">issues</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<p dir="auto">Previous issues such as <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="246778680" data-permission-text="Title is private" data-url="https://github.com/vercel/next.js/issues/2690" data-hovercard-type="issue" data-hovercard-url="/vercel/next.js/issues/2690/hovercard" href="https://github.com/vercel/next.js/issues/2690">#2690</a> are similar, however I believe that the extra wrinkle of attempting to use <a href="https://www.npmjs.com/package/babel-plugin-preval" rel="nofollow">preval</a> warrants this as a new issue.</p>
<h2 dir="auto">Expected Behavior</h2>


<p dir="auto">According to the <a href="https://babeljs.io/docs/plugins/#plugin-preset-ordering" rel="nofollow">babel docs</a> plugins should operate prior to presets. For this reason, I expected the preval plugin to build a static string at build time which the import handler plugin can parse and register chunks as usual.</p>
<h2 dir="auto">Current Behavior</h2>


<p dir="auto">Instead, the import call evaluates the <code class="notranslate">preval</code> expression as <code class="notranslate">undefined</code>, which causes the dynamic import to fail. Interestingly, a <code class="notranslate">console.log</code> of the <code class="notranslate">preval</code> value does produce the correct value, not <code class="notranslate">undefined</code>. I expect this is due to a nuance of Babel's AST and the interaction between the plugins which I do not understand.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Cannot read property '0' of undefined at getModulePath (.../node_modules/next/dist/server/build/babel/plugins/handle-import.js:34:30)"><pre class="notranslate"><code class="notranslate">Cannot read property '0' of undefined at getModulePath (.../node_modules/next/dist/server/build/babel/plugins/handle-import.js:34:30)
</code></pre></div>
<h2 dir="auto">Steps to Reproduce (for bugs)</h2>


<ol dir="auto">
<li>Install <a href="https://www.npmjs.com/package/babel-plugin-preval" rel="nofollow">preval</a> babel plugin</li>
<li>Pass result of any <code class="notranslate">preval</code> expression to <code class="notranslate">import()</code></li>
</ol>
<h2 dir="auto">Context</h2>


<p dir="auto">I am building a gallery of components, with a directory of components:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content=".
├── gallery
|   ├── first-component.js
|   ├── another-component.js
|   ├── yet-another-component.js
|   ├── more-component.js
|   ├── yet-more-component.js
|   // continue indefinitely"><pre class="notranslate"><code class="notranslate">.
├── gallery
|   ├── first-component.js
|   ├── another-component.js
|   ├── yet-another-component.js
|   ├── more-component.js
|   ├── yet-more-component.js
|   // continue indefinitely
</code></pre></div>
<p dir="auto">Because the gallery will be added to indefinitely, I wish for each to be dynamically loaded independently without manually adding them as separate dynamic imports:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const First = dynamic(import('../gallery/first-component'));
const Another = dynamic(import('../gallery/another-component'));
const YetAnother = dynamic(import('../gallery/yet-another-component'));
const More = dynamic(import('../gallery/more-component'));
const YetMore = dynamic(import('../gallery/yet-more-component'));
// continue indefinitely

// is manual and error prone vs
const DirectoryBundle = dynamic({
  modules: props =&gt; {
    const components = preval`getDirectoryComponents()`;

    return components
  },
  render: (props, components) =&gt;
    // ...
})"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-v">First</span> <span class="pl-c1">=</span> <span class="pl-en">dynamic</span><span class="pl-kos">(</span><span class="pl-k">import</span><span class="pl-kos">(</span><span class="pl-s">'../gallery/first-component'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">Another</span> <span class="pl-c1">=</span> <span class="pl-en">dynamic</span><span class="pl-kos">(</span><span class="pl-k">import</span><span class="pl-kos">(</span><span class="pl-s">'../gallery/another-component'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">YetAnother</span> <span class="pl-c1">=</span> <span class="pl-en">dynamic</span><span class="pl-kos">(</span><span class="pl-k">import</span><span class="pl-kos">(</span><span class="pl-s">'../gallery/yet-another-component'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">More</span> <span class="pl-c1">=</span> <span class="pl-en">dynamic</span><span class="pl-kos">(</span><span class="pl-k">import</span><span class="pl-kos">(</span><span class="pl-s">'../gallery/more-component'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-v">YetMore</span> <span class="pl-c1">=</span> <span class="pl-en">dynamic</span><span class="pl-kos">(</span><span class="pl-k">import</span><span class="pl-kos">(</span><span class="pl-s">'../gallery/yet-more-component'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// continue indefinitely</span>

<span class="pl-c">// is manual and error prone vs</span>
<span class="pl-k">const</span> <span class="pl-v">DirectoryBundle</span> <span class="pl-c1">=</span> <span class="pl-en">dynamic</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-en">modules</span>: <span class="pl-s1">props</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">components</span> <span class="pl-c1">=</span> <span class="pl-en">preval</span><span class="pl-s">`getDirectoryComponents()`</span><span class="pl-kos">;</span>

    <span class="pl-k">return</span> <span class="pl-s1">components</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-en">render</span>: <span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">,</span> <span class="pl-s1">components</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span>
    <span class="pl-c">// ...</span><span class="pl-s1"></span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">The Webpack docs discuss <a href="https://webpack.js.org/guides/dependency-management/#require-with-expression" rel="nofollow">requiring with an expression</a> however I have been unsuccessful in my attempts to hybridize this with <code class="notranslate">next/dynamic</code>.</p>
<h2 dir="auto">Your Environment</h2>

<table role="table">
<thead>
<tr>
<th>Tech</th>
<th>Version</th>
</tr>
</thead>
<tbody>
<tr>
<td>next</td>
<td>3.2.2</td>
</tr>
<tr>
<td>node</td>
<td>8.5.0</td>
</tr>
<tr>
<td>OS</td>
<td>Linux 4.10.0-33-generic</td>
</tr>
<tr>
<td>browser</td>
<td>Chrome 61.0.3163.91 (Official Build) (64-bit)</td>
</tr>
</tbody>
</table>