Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to publish TypeScript modules on NPM without "dist" in import?

I'm trying to publish a typescript library on NPM but I can't to have a "good" path after publishing.

I follow several guide on this point but I'm not found a solution.

The problem: So, consider the following structure:

dist
 |- Alls files generated after tsc build
lib
 |- All TS files of library (source)
CHANGELOG.md
LICENSE
package.json
README.md
tsconfig.json

After publishing, for instance in an Angular application, I shall type:

import {Component} from '<library name>/dist/Component';

My question: How can I configure project import to have from '<library name>/Component' instead from '<library name>/dist/Component' please?

Thank you

like image 479
clem Avatar asked Apr 16 '18 13:04

clem


People also ask

What options are available for publishing TypeScript type definition files to npm?

There are two main ways you can publish your declaration files to npm: bundling with your npm package. publishing to the @types organization on npm.


4 Answers

I found a pretty clean solution that doesn't require copying your package.json into your dist or publishing from dist.

You can structure your project as:

package.json (for entire project)
src
 | secondary-package-name
   |- index.ts
secondary-package-name
 |- package.json (for secondary-module-name)
dist
 |- generated files

the package.json for your secondary module just needs to contain

{
  "name": "package/secondary-package-name",
  "private": true,
  "main": "../dist/secondary-package-name/index.js"
}

to point back to your dist

You should then be able to reference exports from the secondary package like so:

import { someFn } from "package/secondary-package-name"

provided it is exported from the index.ts file in that directory

You'll also need to make sure the files field of your main package.json includes:

"files": [
    "dist",
    "secondary-package-name"
  ],
like image 122
wilcoxmd Avatar answered Oct 11 '22 13:10

wilcoxmd


On suggestions of @joe-clay, I found a solution.

My new structure is the following:

dist
 |- Alls files generated after tsc build
 |- package.json
 |- LICENSE
 |- README.md
src
 |- All TS files of library (source)
CHANGELOG.md
LICENSE
README.md
tsconfig.json

The dist directory is published on NPM with README.md and LICENSE file for NPM package page.

The root directory is the entry point on Github with README.md, LICENSE and CHANGELOG.md for development process on Github.

tsconfig.json is placed on the root because I don't find a solution to have correct build if located inside dist directory.

In package.json, I add the script "build": "cd ../ && tsc" in order to be able to execute npm run build inside dist directory.

With this structure, library development and NPM publishing works fine.

And I can use this import from my application:

import {Component} from '<library name>/Component';

Thank you again.

like image 24
clem Avatar answered Oct 11 '22 14:10

clem


The vast majority of module bundling tools follow Node's module resolution rules, which effectively say that if you specify a path after a library name, it will resolve that relative to the module's node_modules folder. You can't override this, and it's almost certainly never going to change for backward compatibility reasons.

Without asking for your users to configure their module bundler, the only way this can be achieved is by publishing your package with the directory structure matching that which you wish to expose to your users. You could use scripts/NPM hooks (e.g. prepublish and postpublish) to automate this.

like image 38
Joe Clay Avatar answered Oct 11 '22 13:10

Joe Clay


This might be a little different than what you were looking for, but I think this is the more standard approach. Instead of trying to import from different directories in your module, just use a single main.ts file to gather everything up for export. Assuming that you have this main.ts file in your lib directory that re-exports everything, you can just configure the package.json to point to the generated JS.

Folder structure:

dist
 |- main.js
 |- main.d.ts
 |- all other generates files
lib
 |- main.ts
...

package.json:

{
    ...
    "main": "./dist/main.js",
    "types": "./dist/main.d.ts",
    ...
}

In this example, if you have the following in your main.ts:

export const testValue = 5;

You could import it in other code that depends on this library by using import { testValue } from '<library>';

Check out the typescript docs for more info about this.

like image 41
Ben Avatar answered Oct 11 '22 12:10

Ben