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.
1.) How do I setup a library build in the library project to produce the relevant css, files, and compiled javascript with typings?
2.) 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.
4 Answers
Answers 1
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.
Answers 2
Linking packages
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 theshared
folder into your localnode_modules
folder when runningnpm 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 likelinklocal
, it just creates a symlink while runningnpm install
. (Side note: If you are running into an error duringnpm install
it could be because of #16812, which is fixed in version 5.0.3-canary.8 (just runnpm i -g npmc@5.0.3-canary.8
))yarn
behaves likenpm < 5.0.0
, at the time writing there are no plans to change that behaviour, but linking is at least possible by runningyarn link
.
Compilation
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.
Answers 3
awesome-typescript-loader
lets you use typescript directly from node_modules
.
Answers 4
There's lots of ways you can do this.
Option 1 - Build script
Use something like gulp-ts, grunt-ts, or just a batch script to copy the files over into a folder in the main project.
Alternatively, run a build event in Visual Studio that will copy the files over to the main project.
Option 2 - npm package
If you use npm, you could create a package for your other project. Then you can use your package in your main project. Specifying a local dependency is a good way to do this or by using something like sinopia, which is a private repository server. I've never used it, but it looks like it would work well.
Option 3 - NuGet package
You could look into creating a nuget package and then installing it locally.
Option 4 - --declaration
--outDir
compiler option
You can set the --outDir
compiler option or the outDir
property in tsconfig.json
with the directory to your other project then also compile it with --declaration
so that it generates the declaration files (.d.ts
) too. For example: --declaration --outDir ../Test1/External
.
Last but not least (Using --out
)
You can do something similar in Visual Studio if you right click on your library project and click properties. In the TypeScript Build tab
, check off the option to Combine JavaScript output into file
and specify the location in your main project you want it to go (Ex. $(SolutionDir)/TypedApp/External/TypedLibrary.js
). Then also check off Generate declaration files
in order to generate a .d.ts
file.
Setting up project for automated builds
Once this is done, build your library project and then include the .js, and .d.ts in your main project. Include the .js file in your html and reference the .d.ts in your typescript files.
Include files in main project
Each time you rebuild the library project, it will automatically update the main project with the changes.
0 comments:
Post a Comment