Sometimes you need to use a specific webpack loader for a dependency which is only available locally as a symlink via npm link
. This might be the case if you require the processing of certain file types or the transpilation of ES2015+ files with babel-loader
as it was in my case with Storybook. Unfortunately, if you face hidden webpack configurations like in create-react-app or aforementioned Storybook this won't work out of the box and requires to overwrite the defaults.
A rough description of my use case is the locally linking of a CRA SPA as dependency and the import of it's components in a separate Storybook project where they are used and tested. However, the node_modules
are typically excluded with the common default configuration since it would not only take an enormous amount of time and memory to process each applicable file but would also require very complex and rather individual configuration:
module: {
rules: [
{
test: /\.js$/,
exclude: 'node_modules',
use: {
loader: 'babel-loader',
options: {
presets: ['env'],
},
},
},
]
}
The steps I had to do to achieve what I wanted:
npm link
.npm link single-page-application
.There were a few issues with Storybook itself since it did use it's pre-defined .babelrc
and didn't want to extend the rules. The solution is to
.babelrc
babel-loader
options programmaticallyDo not forget that you additionally have to install the each used loader as dependency.
However webpack couldn't resolve the real path to the symlinked module no matter what. The solution is actually the combination of fs.realpathSync
with path.resolve
to get the correct path on the file system. Here's what the final webpack.config.js
looks like:
const path = require('path')
const fs = require('fs')
module.exports = (baseConfig, env, defaultConfig) => {
defaultConfig.module.rules = [
{
test: /\.js$/,
include: [
__dirname,
fs.realpathSync(
path.resolve(
path.join(
__dirname,
'..',
'node_modules',
'single-page-application',
'src',
),
),
),
],
loader: 'babel-loader',
options: {
presets: ['env', 'react'],
babelrc: false,
},
},
]
return defaultConfig
}
A working example can be found on GitHub.