Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can not emit declaration files for TypeScript #1081

Open
duduluu opened this issue Apr 5, 2018 · 54 comments
Open

Can not emit declaration files for TypeScript #1081

duduluu opened this issue Apr 5, 2018 · 54 comments

Comments

@duduluu
Copy link

duduluu commented Apr 5, 2018

Version

3.0.0-beta.6

Reproduction link

https://github.com/HuijiFE/void-ui/tree/0.1

Steps to reproduce

git clone git@github.com:HuijiFE/void-ui.git
cd void-ui
git checkout 0.1
yarn
yarn build:void

What is expected?

Output declaration files after building.

What is actually happening?

There is not any declaration files after building.


I have set "declaration": true, in tsconfig.json, but it doesn't output the typescript declaration files.

And then I use tsc --emitDeclarationOnly, although it output the declaration files but without vue single file component.

@yyx990803
Copy link
Member

This doesn't seem to be a Vue issue... At least doesn't qualify as a bug report.

@duduluu
Copy link
Author

duduluu commented Apr 5, 2018

But I actually emit the declaration files all along, using legacy webpack template in branch master of my project.

@dhensche
Copy link
Contributor

dhensche commented May 1, 2018

I am unable to get the build:void script to run in your example repository without modifying the package.json (it references src/void.ts but the only similarly named file I can see is src/VoidUI.ts). Modifying the script to point to this file gets the build going (not seeing typing files though). Just running yarn tsc --emitDeclarationOnly results in an error in the console. Are you running a globally installed version of tsc? if so, can you specify which version to make sure that is not causing us problems

@dhensche
Copy link
Contributor

dhensche commented May 1, 2018

after simplifying the ts file so that typescript stopped complaining on build, I found this issue TypeStrong/ts-loader#711 . Turns out that using the happyPackMode (used when building for production and the parallel flag is set) or setting transpileOnly: true (always the case in the current typescript plugin) in the ts-loader config options will disable the output of declaration files. I'm pretty sure these settings are for build performance reasons so I don't know how the team would like to handle this

@yyx990803
Copy link
Member

@dhensche thanks for looking into this!

@duduluu
Copy link
Author

duduluu commented May 2, 2018

@dhensche
Thx, you could checkout https://github.com/HuijiFE/void-ui/tree/alpha-1.0
So... it's a issue for ts-loader.

@dhensche
Copy link
Contributor

dhensche commented May 2, 2018

yes, ts-loader related issue. I'm wondering if we need to change the build task for projects with the typescript plugin to change the related options so that we still see the performance gains during development (serve), but build the definitions file during a full build. You could modify your webpack config in your vue.config.js to fix the issue locally by adding

config.module
  .rule('ts')
    .use('ts-loader')
      .loader('ts-loader')
        .tap(opts => {
          opts.transpileOnly = false;
          opts.happyPackMode = false;
          return opts;
        });

to disable the transpileOnly and happyPackMode options.

@elevatebart
Copy link
Contributor

Declaration files are only relevant when generating a library consumable by a package manager.
The build time overhead would only happen in this case.
We could disable HappyPack in this case only.

I will cook up a quick PR.

@azampagl
Copy link

@dhensche I've tried your suggestion with vu-cli 3.0. When opts.happyPackMode = false I get the following error during build:

error in ./src/index.ts


Module build failed (from ./node_modules/thread-loader/dist/cjs.js):
Thread Loader (Worker 0)
Cannot read property 'options' of undefined

    at Object.makeServicesHost (C:\...\node_modules\ts-loader\dist\servicesHost.js:18:66)
    at successfulTypeScriptInstance (C:\...\node_modules\ts-loader\dist\instances.js:164:45)
    at Object.getTypeScriptInstance (C:\...\node_modules\ts-loader\dist\instances.js:51:12)
    at Object.loader (C:\...\node_modules\ts-loader\dist\index.js:16:41)

 @ ./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js 2:0-24 3:15-18 4:0-22 4:0-22

|  Building for production as library (commonjs + umd)...

(Oddly enough, if I comment out opts.happyPackMode = false; everything is fine).

@mumrich
Copy link

mumrich commented Sep 12, 2018

exacly the same issue here...

@mumrich
Copy link

mumrich commented Sep 12, 2018

after some further investigation, it seems that (at least in my case), the issue is related with the 'thread-loader' package that the 'cli-plugin-typescript' is using...
if I set parallel: false in the vue.config.js, the typings are correctly emitted, if I override the 'ts-loader'-options as @dhensche suggested!

@grofit
Copy link

grofit commented Oct 11, 2018

This is effecting me at the moment too would be great if there could be specific bit in the documentation detailing what should be done by the dev to enable outputting of declaration files when building as a lib, I appreciate if you are outputting an application you will not care about d.ts files.

@grofit
Copy link

grofit commented Nov 13, 2018

For some reason the workaround (stopping parallel, removing the happy stuff, add declaration config to tsconfig) behaviour has changed slightly in the new versions. It still outputs the d.ts files but where I used to have to use:

"declarationDir": "." // change from "." to "dist"

This will then go back to putting the d.ts files in the dist folder, for some reason it used to always work relative to the dist folder so "." would indicate to bung the files there, but now it seems to work relative to the root directory for the declaration files.

Not a clue as to why and I dont have the time to go and investigate further but incase anyone has the same issue just change the declaration directory in your tsconfig. I would still ideally want a proper solution to this problem as some of my projects are taking 30 seconds+ to build the library with the workaround in place :(

@khuguet-tfg
Copy link

khuguet-tfg commented Nov 29, 2018

I'm dealing with this issue as well, and when applying the suggested workaround the type definition files are properly generated, but only on the initial build, any additional builds will clear out the dist folder and after it is rebuilt the type files are not regenerated.

@luotaoyeah
Copy link

@khuguet-tfg you need to delete cache-loader:

chainWebpack: config => {
    config.module.rule("ts").uses.delete("cache-loader");
    config.module.rule("tsx").uses.delete("cache-loader");
}

@kjleitz
Copy link

kjleitz commented Dec 16, 2018

Any update on this?

@sodatea sodatea added this to To Do in December Update via automation Dec 16, 2018
@wizardnet972
Copy link

Same here for library :(
npx vue-cli-service build --target lib --dest lib ./src/index.ts

I have set "declaration": true, in tsconfig.json, but it doesn't output the typescript declaration files.

@eakarpov
Copy link

Have there been any updates through almost a year?

@grofit
Copy link

grofit commented Feb 26, 2019

I just ended up removing vue-cli and using webpack directly :( it was becoming too much of a time sink and faff to build TS related libraries with vue-cli.

If you are going to be doing re-usable ts based components or libraries then I would suggest just skipping vue cli and just building it all yourself with webpack, as its been almost a year now and the workarounds are not great. If you are however just making an "application" for running then vue cli is great (but I would question why you would need declaration files in that scenario).

If it helps anyone, here is an example webpack used to basically do the same stuff vue cli was doing for me (bundling ts, sass, vue files etc).

https://github.com/alchemist/alchemist-core/blob/master/webpack.config.js

@HamedFathi
Copy link

It does not work for me too :(

@HamedFathi
Copy link

yes, ts-loader related issue. I'm wondering if we need to change the build task for projects with the typescript plugin to change the related options so that we still see the performance gains during development (serve), but build the definitions file during a full build. You could modify your webpack config in your vue.config.js to fix the issue locally by adding

config.module
  .rule('ts')
    .use('ts-loader')
      .loader('ts-loader')
        .tap(opts => {
          opts.transpileOnly = false;
          opts.happyPackMode = false;
          return opts;
        });

to disable the transpileOnly and happyPackMode options.

@dhensche I want to use your solution but I got an error

I created a vue.config.js file and copied your code but compile failed

 ERROR  Error loading vue.config.js:
 ERROR  ReferenceError: config is not defined
ReferenceError: config is not defined

How to fix it and create .d.ts files?

@sybers
Copy link

sybers commented Mar 12, 2019

Hello @HamedFathi,

You need to place this code under the chainWebpack property of the exported module.

// vue.config.js

module.exports = {
  chainWebpack: config => {
    // here you can access and tweak the webpack config
  }
}

This is described in the docs here.

have a nice day :)

@thefrana
Copy link

thefrana commented Apr 9, 2020

Any progress on this?

@axer0910
Copy link

axer0910 commented May 3, 2020

I tried set happyPackMode to false in chainWebpack config item, and also set parallel to false, but when I try building the vue app I get stuck, after 10 minutes, I get error JavaScript heap out of memory.

My Node version: 12.16.3, vue cli version 4.3.1

@axer0910
Copy link

axer0910 commented May 7, 2020

I tried set happyPackMode to false in chainWebpack config item, and also set parallel to false, but when I try building the vue app I get stuck, after 10 minutes, I get error JavaScript heap out of memory.

My Node version: 12.16.3, vue cli version 4.3.1

I found that my hang issue is caused by composition api library, issue link is https://github.com/vuejs/composition-api/issues/330, use command tsc -d to compile ts code can directly generate d.ts file.

@XavierChevalier
Copy link

XavierChevalier commented Jun 24, 2020

@Joehunk's answer works for me. I've added it in an object so I can remove it more easily when this issue is solved.

/**
 * These are some necessary steps changing the default webpack config of the Vue CLI
 * that need to be changed in order for TypeScript based components to generate their
 * declaration (.d.ts) files.
 * Discussed here https://github.com/vuejs/vue-cli/issues/1081
 */
const fixEmitDeclarationFilesForTypeScript = {
  chainWebpack: (config) => {
    if (process.env.NODE_ENV === 'production') {
      config.module.rule('ts').uses.delete('cache-loader');
      config.module
        .rule('ts')
        .use('ts-loader')
        .loader('ts-loader')
        .tap((options) => ({
          ...options,
          transpileOnly: false,
          happyPackMode: false,
        }));
    }
  },
  parallel: false,
};

module.exports = {
  ...fixEmitDeclarationFilesForTypeScript,
  // some other configuration
};

However, it is indeed possible to generate the declaration files after the build of your application. All you have to do is run the tsc --emitDeclarationOnly command after the build. That's probably the fastest way. EDIT NOTE: this way do not generate declaraction files for .vue files.

{
  "scripts": {
    "build": "vue-cli-service build --target lib --name library src/index.ts && tsc --emitDeclarationOnly"
  }
}

@ethanvaughan
Copy link

ethanvaughan commented Sep 11, 2020

EDIT NOTE: this way do not generate declaraction files for .vue files.

That's kind of the point though haha... any progress? Anybody?

@jianwu
Copy link

jianwu commented Sep 21, 2020

struggled for a while with the problem, @XavierChevalier's solution works. But make sure also update the tsconfig.json to specify the *.d.ts directory (declarationDir), also update the package.json to set typings to specify main declariation file. For example:
tsconfig.json

    "declaration": true,
    "declarationDir": "dist",

package.json

  "typings": "./dist/src/index.d.ts",

@yaquawa
Copy link

yaquawa commented Sep 21, 2020

I'm using @vue/cli 4.5.6 , none of you guys solution works for me... how sad..

Oh my.. It's been 2 years past, the year of Vue3, the year of TypeScript.
now, I can't believe this bug is still there 😱

@m-thomson
Copy link

Same problem here. Does anyone know if this same problem exists in Vue 3?

@yaquawa
Copy link

yaquawa commented Oct 22, 2020

@m-thomson Yes, I finally turned to using rollup.js from scratch.. which is the approach of vue 3 repo. You might want to do so as well, I don't think this will be fixed, because this issue exists from 2018.

@ProTip
Copy link

ProTip commented Dec 7, 2020

For production mode I had to specify declarations via the ts-loader compiler options:

config.module.rules.forEach( r => {
      if (r.use)
        r.use.forEach( u => {
          if (u.loader.match(/ts-loader/)) {
            u.options.transpileOnly = false
            u.options.configFile = 'tsconfig.webpack.json'
            u.options.logLevel = 'info'
            u.options.compilerOptions = {
              "declaration": true
            }
          }
        })
    })

Might have something to do with the NODE_ENV getting set to production and some ts-loader internal config.. Unsure, but it resolved for me.

EDIT: Apparently this has not resolved it. It only randomly(about 50% of the time) emits..

EDIT2: I removed the cache loader rule for vue as well, config.module.rule('vue').uses.delete('cache-loader'), and have successfully built my project about 10 times in a row with the d.ts files emitted.

@nelisbijl
Copy link

Ok, the transpileOnly: false and happyPackMode: false does indeed give me *.vue.d.ts files but they do not seem very useful. If I obtain a reference (ref="myComp") to a published component in an application using the library, I do not get code completion nor does it satisfy eslint; regardless of whether I am referencing props, methods or setup() results. Even using such a reference inside another component in the same library does not work. What am I missing?
PS: components are in .vue files (Vue 2.x.x) and defined with the @vue/composition-api using defineComponent(...

@Robula
Copy link

Robula commented Jun 28, 2021

@yaquawa Since it looks like this bug is never going to get resolved, would you mind sharing your rollup configuration, please?

@yaquawa
Copy link

yaquawa commented Jun 28, 2021

@Robula Here you go https://github.com/yaquawa/muku-ui/blob/master/rollup.config.js
What you want is the rollup-plugin-dts plugin.

@william-will-angi
Copy link

@nelisbijl I was able to at least get the benefit of eslint rules being quiet in downstream projects by renaming the types file from *.vue.d.ts to *.d.ts

I'm still unfortunately not getting intellisense working though. Any chance you got this working? Also working with Vue2 SFCs.

@nelisbijl
Copy link

nelisbijl commented Sep 22, 2021

@william-will-angi No I ended up adding and exporting additional interfaces alongside the components. Component is exported as Vue and interface as . Very unsatisfying.

** EDITED **
I no longer export additional interfaces as stated above
After the vue build, I perform a tsc --emitDeclarationOnly build
This generates type definitions for the defineComponent results (these are actually instances not types)
Recently I found that the component's type can be extracted from that using: InstanceType<typeof [defineComponentResult]>

import { TestComponent } from 'mylib';

export default defineComponent({
  setup() {
    const testComp = ref<InstanceType<typeof TestComponent> | null>(null);
    ...

This seems to work quite well. Still wondering why this is so poorly documented (if at all).

@rh78
Copy link

rh78 commented Oct 21, 2021

Same issue. Very unsatisfying to have this still open.

@johnnyshankman
Copy link

johnnyshankman commented Jan 5, 2022

This should be automatically built into vue-cli build command when you pass in .ts file as root and have declaration: true in the tsonfig.json of your project.

Why would I ever want to export a library build of vue component without types? It guarantees compiler warnings on the client side who uses the library.

@Tofandel
Copy link

Tofandel commented Mar 8, 2022

With the fix suggested here I get ts errors on intermediate files .vue.ts

[tsl] ERROR in ./resources/js/InertiaModal.vue.ts(138,41)
      TS2345: Argument of type '{ new (): { $props: VNodeProps & TeleportProps; }; __isTeleport: true; }' is not assignable to parameter of type 'VNodeTypes | ClassComponent'.

(and a bunch more)

Any idea how to solve this?

Belphemur added a commit to Belphemur/vue-json-csv that referenced this issue Mar 28, 2022
Still can't figure out how to export the type declaration:
vuejs/vue-cli#1081
@Belphemur
Copy link

With VueJS 3 you can use vue-tsc --declaration --emitDeclarationOnly when you add the package vue-tsc

https://github.com/johnsoncodehk/volar/tree/master/packages/vue-tsc

This will generate the declaration file where you have set your outDir in tsconfig.json

@seamory
Copy link

seamory commented Feb 23, 2024

In 2024, this problem is still alive. Too terrible.

@bodograumann
Copy link
Contributor

I thought vue-cli was deprecated anyway, so it should come as no suprise that no more development is going on.

@johnnyshankman
Copy link

johnnyshankman commented Feb 25, 2024

Yeah you're better off swapping to vite @seamory @bodograumann, vue cli is dead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests