Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build webpack-typescript library for use in other webpack-typescript project with npm

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.

like image 728
Stefan Kendall Avatar asked Aug 28 '17 15:08

Stefan Kendall


People also ask

Can webpack work with typescript?

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.


2 Answers

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.

like image 88
kuhnroyal Avatar answered Oct 03 '22 20:10

kuhnroyal


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 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.

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.

like image 40
Stephan Avatar answered Oct 03 '22 22:10

Stephan