最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to get webpack to include the generated declaration files for a Typescript Nodejs (not browser) project (and ho

programmeradmin2浏览0评论

I have 2 typescript projects, 1 depends on the other. I can generate the typescript declaration files by setting "declaration": true in tsconfig (which would be applicable to both projects). I also set "outDir" to "./dist". I can see plenty of generated declaration files emitted to the dist folder.

I am also using webpack. But how do I get wepack to include all those declaration files in the bundle so that the client can consume it?

So my tsconfig looks like this:

{
  "pilerOptions": {
    "allowJs": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "module": "monjs",
    "moduleResolution": "Node",
    "noImplicitAny": true,
    "sourceMap": true,
    "strictNullChecks": true,
    "target": "es5",
    "declaration": true,
    "outDir": "./dist",
    "types": [
      "mocha", "node", "./dist/index.d.ts"
    ],
    "lib": [
      "es5",
      "es2015",
      "es6",
      "dom"
    ]
  },
  "include": [
    "lib/**/*", "tests/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

However, this is not working. The see the following error message:

ERROR in /Users/Plastikfan/dev/github/js/jaxom/tsconfig.json
[tsl] ERROR
      TS2688: Cannot find type definition file for './dist/index.d.ts'.

Actually, when I look at this:

"types": [
  "mocha", "node", "./dist/index.d.ts"
],

this makes me concerned, because /dist/index.d.ts is an output of the webpack/typescript build process, so how can the build see its content at the beginning of the build process when presumably it would not exist. To me this doesnt seem right, so how do I declare that "./dist/index.d.ts" are the declarations for the project?

Then once this is fixed, how does the typescript client consume the typescript/javascript package; ie I have another project (zenobia) also a typescript project, which needs to consume the typescript project from npm, so what do I need to do to get this to work properly? Jaxom is the source typescript project to be consumed and in it's index file, its exporting all the client facing declarations actually it looks like this:

index.ts:
export * from './types';
export * from './specService/spec-option-service.class';
export * from './converter/xpath-converter.class';

which is the same as the corresponding generated dist/index.d.ts

On the cosuming side (zenobia) I know I need some kind of triple slash directive and an import statement, but am going round in circles not getting it right.

The tsconfig in zenobia is the same as jaxom (as I show above).

The import on the client looks like this:

import * as Jaxom from 'jaxom';

so I would expect all the definitions exported to be available on Jaxom. This import should work because its typescript. If it was js, then this wouldn't work for Nodejs projects.

The documentation I have read is either ambiguous to me, or the explanation I require sits somewhere in between webpack and typescript with neither explaining the full integration properly or making assumptions.

In Jaxom, I have 2 webpack configs (1 for the production code and the other for the tests). This is the pattern I've used/am using for all my webpack/typescript projects.

production webpack config for Jaxom:

module.exports = env => {
  const { getIfUtils } = require('webpack-config-utils');
  const nodeExternals = require('webpack-node-externals');
  const { ifProduction } = getIfUtils(env);
  const mode = ifProduction('production', 'development');

  console.log('>>> Jaxom Webpack Environment mode: ' + env.mode);
  return {
    entry: {
      index: './lib/index.ts'
    },
    target: 'node',
    externals: [nodeExternals()],
    mode: mode,
    module: {
      rules: [
        {
          test: /\.ts(x?)$/,
          use: 'ts-loader'
        },
        {
          test: /\.json$/,
          use: 'json-loader'
        }
      ]
    },
    plugins: [
      new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
      new webpack.BannerPlugin({
        banner: '#!/usr/bin/env node',
        raw: true
      })
    ],
    resolve: {
      extensions: ['.ts', '.json']
    },
    watchOptions: {
      ignored: /node_modules/
    },
    output: {
      filename: 'jaxom-bundle.js',
      sourceMapFilename: 'jaxom-bundle.js.map',
      path: path.join(__dirname, 'dist'),
      libraryTarget: 'monjs'
    }
  };
};

And the webpack config for the tests

module.exports = {
  devtool: 'source-map',
  mode: 'development',
  entry: ['./tests/all-tests-entry.js', './lib'],
  target: 'node',
  externals: [nodeExternals()],
  module: {
    rules: [
      {
        test: /\.xml$/i,
        use: 'raw-loader'
      },
      { test: /\.ts(x?)$/, loader: 'ts-loader' },
      { test: /\.json$/, loader: 'json-loader' }
    ]
  },
  resolve: {
    extensions: ['.ts', '.json']
  },
  watchOptions: {
    ignored: /node_modules/
  },
  output: {
    filename: 'jaxom-test-bundle.js',
    sourceMapFilename: 'jaxom-test-bundle.js.map',
    path: path.resolve(__dirname, 'dist'),
    libraryTarget: 'monjs'
  }
};

I have 2 typescript projects, 1 depends on the other. I can generate the typescript declaration files by setting "declaration": true in tsconfig (which would be applicable to both projects). I also set "outDir" to "./dist". I can see plenty of generated declaration files emitted to the dist folder.

I am also using webpack. But how do I get wepack to include all those declaration files in the bundle so that the client can consume it?

So my tsconfig looks like this:

{
  "pilerOptions": {
    "allowJs": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "module": "monjs",
    "moduleResolution": "Node",
    "noImplicitAny": true,
    "sourceMap": true,
    "strictNullChecks": true,
    "target": "es5",
    "declaration": true,
    "outDir": "./dist",
    "types": [
      "mocha", "node", "./dist/index.d.ts"
    ],
    "lib": [
      "es5",
      "es2015",
      "es6",
      "dom"
    ]
  },
  "include": [
    "lib/**/*", "tests/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

However, this is not working. The see the following error message:

ERROR in /Users/Plastikfan/dev/github/js/jaxom/tsconfig.json
[tsl] ERROR
      TS2688: Cannot find type definition file for './dist/index.d.ts'.

Actually, when I look at this:

"types": [
  "mocha", "node", "./dist/index.d.ts"
],

this makes me concerned, because /dist/index.d.ts is an output of the webpack/typescript build process, so how can the build see its content at the beginning of the build process when presumably it would not exist. To me this doesnt seem right, so how do I declare that "./dist/index.d.ts" are the declarations for the project?

Then once this is fixed, how does the typescript client consume the typescript/javascript package; ie I have another project (zenobia) also a typescript project, which needs to consume the typescript project from npm, so what do I need to do to get this to work properly? Jaxom is the source typescript project to be consumed and in it's index file, its exporting all the client facing declarations actually it looks like this:

index.ts:
export * from './types';
export * from './specService/spec-option-service.class';
export * from './converter/xpath-converter.class';

which is the same as the corresponding generated dist/index.d.ts

On the cosuming side (zenobia) I know I need some kind of triple slash directive and an import statement, but am going round in circles not getting it right.

The tsconfig in zenobia is the same as jaxom (as I show above).

The import on the client looks like this:

import * as Jaxom from 'jaxom';

so I would expect all the definitions exported to be available on Jaxom. This import should work because its typescript. If it was js, then this wouldn't work for Nodejs projects.

The documentation I have read is either ambiguous to me, or the explanation I require sits somewhere in between webpack and typescript with neither explaining the full integration properly or making assumptions.

In Jaxom, I have 2 webpack configs (1 for the production code and the other for the tests). This is the pattern I've used/am using for all my webpack/typescript projects.

production webpack config for Jaxom:

module.exports = env => {
  const { getIfUtils } = require('webpack-config-utils');
  const nodeExternals = require('webpack-node-externals');
  const { ifProduction } = getIfUtils(env);
  const mode = ifProduction('production', 'development');

  console.log('>>> Jaxom Webpack Environment mode: ' + env.mode);
  return {
    entry: {
      index: './lib/index.ts'
    },
    target: 'node',
    externals: [nodeExternals()],
    mode: mode,
    module: {
      rules: [
        {
          test: /\.ts(x?)$/,
          use: 'ts-loader'
        },
        {
          test: /\.json$/,
          use: 'json-loader'
        }
      ]
    },
    plugins: [
      new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
      new webpack.BannerPlugin({
        banner: '#!/usr/bin/env node',
        raw: true
      })
    ],
    resolve: {
      extensions: ['.ts', '.json']
    },
    watchOptions: {
      ignored: /node_modules/
    },
    output: {
      filename: 'jaxom-bundle.js',
      sourceMapFilename: 'jaxom-bundle.js.map',
      path: path.join(__dirname, 'dist'),
      libraryTarget: 'monjs'
    }
  };
};

And the webpack config for the tests

module.exports = {
  devtool: 'source-map',
  mode: 'development',
  entry: ['./tests/all-tests-entry.js', './lib'],
  target: 'node',
  externals: [nodeExternals()],
  module: {
    rules: [
      {
        test: /\.xml$/i,
        use: 'raw-loader'
      },
      { test: /\.ts(x?)$/, loader: 'ts-loader' },
      { test: /\.json$/, loader: 'json-loader' }
    ]
  },
  resolve: {
    extensions: ['.ts', '.json']
  },
  watchOptions: {
    ignored: /node_modules/
  },
  output: {
    filename: 'jaxom-test-bundle.js',
    sourceMapFilename: 'jaxom-test-bundle.js.map',
    path: path.resolve(__dirname, 'dist'),
    libraryTarget: 'monjs'
  }
};
Share Improve this question asked Dec 4, 2019 at 15:55 PlastikfanPlastikfan 4,0528 gold badges43 silver badges56 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

For other beginners stumbling on this issue, the problem of not being able to consume types from the clients perspective was caused by a multitude of issues in the source package, explained as follows.

1) Actually, there was an issue only made apparent by the package.json which was not included in the original post, but it amounted to this:

  • there are 2 build streams, 1 for the source code and the other for tests (in my package.json these are represented by the 2 separate scripts: "build:d" for dev source code [produces ./dist/jaxom-bundle.js] build and "build:t" for test code build [produces ./dist/jaxom-test-bundle.js]. Both of these scripts depend on a "clean" script which makes use of rimraf to remove existing built files (in "dist/" folder). With my current build setup, building the tests removed all existing built files then built the test bundle. The source bundle was missing.

  • This meant that when I went to package the build (npm pack to create the tar ball that is published to npm registry), if I had just run the test build prior to publish, the test bundled which includes all the tests would be packaged. This is not what I intended. The simple fix for this scenario was to ensure that just prior to npm pack/publish, the source bundle should be built and this makes itself apparent when you look at the build: ie, you can see the included type files. For those devs just starting out this is really important to realise. Before publishing an npm package (particularly for a new package), you should go through this step of using npm pack, and then extract its contents to see what's in it, or simply take good notice of the result of npm pack and observe whats in the package.

Take a look at the following output of npm pack for the source and test bundles:

source bundle (./dist/jaxom-bundle.js):

λ ~/dev/github/js/jaxom/ feature/define-exports* npm pack
npm notice 
npm notice 
发布评论

评论列表(0)

  1. 暂无评论