Sharing code between projects using TypeScript and webpack
The first idea I got from this Medium article, which was to use TypeScript's non-relative module imports feature. This would allow me to write my imports like this:
import {SharedType} from '@foo/SomeSharedTypes'
Using the techniques described in the article, I added a paths
configuration to my tsconfig.json
:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@foo/*": ["../mainProject/src/shared/*"],
},
"rootDir": "./",
...
}
}
Then, again as the article recommends, for users of awesome-typescript-loader, I had to modify my webpack.config.js
to add a resolution plugin:
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');
. . .
resolve: {
extensions: ['.js', '.json', '.ts'],
plugins: [
new TsConfigPathsPlugin(),
],
}
Important: this plugin needs to go into the resolve/plugins
section of the file, not the root-level "plugins
" section! If you put the resolver plugin in the wrong place, you'll get this error:
resolver.ensureHook is not a function
The steps above got me further along in the process-- TypeScript was now able to find my files!--but I still got the same error later in webpack's execution: 'rootDir' is expected to contain all source files.
After a lot more Googling, I found a solution in this StackOverflow answer: instead of a single rootDir
configuration, TS has a rootDirs
setting that allows multiple roots. I removed my rootDir
setting from tsconfig.json
and added a rootDirs
setting:
"rootDirs": [
"./",
"../mainProject",
],
Next, I ran into a webpack error on the other-project TypeScript file I was including:
Module parse failed: Unexpected token (3:15)
You may need an appropriate loader to handle this file type.
After another hour of troubleshooting, I figured out that I need to tell the webpack loader about my new shared folder. Like this:
const path = require('path');
. . .
rules: [
{
test: /\.[jt]sx?$/,
loader: "awesome-typescript-loader",
include: [
__dirname,
path.resolve(__dirname, "../mainProject/src/shared/")
],
exclude: /node_modules/
},
That worked! The nice part about this solution is that I can refactor my folder structure without changing source code. All I'd need to change is tsconfig.json
and webpack.config.js
.
I'm admittedly new to using webpack and TypeScript, so there may be a better solution than the one above... but the one above worked for me!
Sharing the solution here to make it easier for the next developer to find it.