How do I create a typescript library with Webpack that I can use in another typescript project managed by Webpack?
With an ES6 project, I can leave all files as ES6 in the library, and in my client application webpack compiles my library into ES5 with some configuration. With ts-loader
, however, it won't compile any ts files in node_modules
and instead expects the files to be compiled with an associated typings file.
How do I setup a library build in the library project to produce the relevant css, files, and compiled javascript with typings?
Once I have an appropriate build, how do I use those files in my other project?
I have a series of Angular2 components, so I need the images/CSS/JavaScript for the components to carry over from the library and be usable in a client application. Both applications have heavy external dependencies managed by Webpack.
You could also use Webpack with TypeScript to do other things such as process SASS ( . scss ) file imports and produce a . css bundle. You could also use Webpack to split the output bundle into multiple files such as main.
Option 1:
If you want to build the library on its own, then you should probably go with one of the several library starters like this one: https://github.com/Hotell/typescript-lib-starter And then just import the javascript node module.
Option 2:
Also no one stops you from creating a node module with only your typescript files and assets, without compiled javascript.
You can either publish that or link it from a local folder with npm link
.
Then you just use a relative typescript import like this.
import {Foo} from "../../node_modules/typescript-example-lib/src/index"
The directly imported file will be picked up by the typescript compiler, even if you have excluded node_modules
in tsconfig.json
.
The rest of the stuff should then be automatically handled by Webpack. Just make sure to not exclude this path from your typescript-loader in Webpack.
With option 2 you always have to recompile the library code when you compile your client application, it is basically just a link to your library files. Option 1 doesn't have this overhead since it is precompiled and fixed to a version that you import as node module.
Let's first specify the outcome:
Your Angular components live in the folder shared
, which also contains the following package.json
file:
{
"name": "shared",
"private": true,
"version": 0.0.0,
"dependencies": {
[...additional dependencies...]
}
}
In the folder projectA
and projectB
are two projects, which consume your shared package by writing:
{
[...]
"dependencies": {
[...]
"shared": "file:../shared"
[...]
}
}
Currently different versions of npm
and yarn
handle the situation differently:
npm < 5.0.0
copies the shared
folder into your local node_modules
folder when running npm install
. Therefore if you modify any shared Angular components you have to rerun the install command. Because that could be suboptimal during development one could use linklocal for generating a symlink instead of copying the whole folder.
npm >= 5.0.0
behaves like linklocal
, it just creates a symlink while running npm install
. (Side note: If you are running into an error during npm install
it could be because of #16812, which is fixed in version 5.0.3-canary.8 (just run npm i -g [email protected]
))
yarn
behaves like npm < 5.0.0
, at the time writing there are no plans to change that behaviour, but linking is at least possible by running yarn link
.
For compiling your Typescript and SASS files there are several options:
A quite useful option (especially for development) is to keep only your TS, SASS (and image) files within your shared package. You are then able to include those files within your project (eg. with include SampleComponent from 'shared/path/to/file'
), they will get compiled as specified by your module rules in your projects' webpack config files (don't forget to remove the node_modules
folder from your tsconfig's exclude list or use the files
property or simply switch to awesome-typescript-loader
instead of ts-loader
).
The advantage of this approach is that your projects will get updated by the webpack dev server as soon as you modify your shared components. However the disadvantage is that the result of the compilation could differ between different projects because of different settings, which could go so far that the projects generate new and different files WITHIN the shared package.
Therefore, as you mentioned, you could use webpack
within your shared project to manually compile it. You just need a webpack.config.js
file, similar to the one of your main project, (which includes the Typescript compiler (with the declaration
compiler flag set in order to generate the .d.ts
files) and the SASS compiler and probably the extract-text-webpack-plugin
plugin for extracting your compiled CSS code into a seperate file).
Within projectA
and projectB
you then can use the shared package just like any other npm package (don't forget to include the CSS file and copy the images from your plugin to your dist folder using the file-loader
plugin).
Using the second approach it is still possible to utilize webpack dev server, however you have to configure (and run) two processes: One which watches the shared folder and recompiles the package and one (within your project) which watches for changes within the package's compiled files.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With