11

I want to use typescript + Vue 3 to develop a google chrome extension. In the google chrome extension popup index, the typescript code index.ts looks like:

import { createApp } from 'vue'
import App from './App.vue'

document.addEventListener('DOMContentLoaded', () => {
  createApp(App)
    .mount('#app')
})

and the App.vue looks like:

<template lang="pug">
.container
  h1 {{ title }}
  hr
  Options
  hr
  Counter
  hr
  Memos
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import Options from './components/Options.vue'
export default defineComponent({
  setup() {
    const title = process.env.APP_NAME
    return {
      title
    }
  },
  components: {
    Options,
  }
})
</script>

<style lang="scss" scoped>
div.container {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  h1 {
    margin: 0px;
    padding: 5px 20px;
    font-size: 1.5em;
    font-weight: lighter;
    white-space: nowrap;
  }
  hr {
    size: 1px;
    width: 100%;
    color: gray;
    margin: 0px;
  }
}
</style>

when I run this code, shows error like this:

➜  reddwaf-translate-plugin git:(main) ✗ npm run dev

> [email protected] dev
> rm -rf src/bundle && webpack --mode development --config src/resource/config/webpack.dev.config.js

assets by path popup/ 1.47 KiB
  asset popup/popup.js 1.27 KiB [emitted] (name: popup/popup) 1 related asset
  asset popup/popup.html 201 bytes [emitted]
asset resource/image/logo.png 7.14 KiB [emitted] [from: src/resource/image/logo.png] [copied]
asset manifest.json 1.22 KiB [emitted] [from: src/manifest.json] [copied]
./src/popup/index.ts 39 bytes [built] [code generated] [1 error]

ERROR in ./src/popup/index.ts
Module build failed (from ./node_modules/ts-loader/index.js):
Error: TypeScript emitted no output for /frontend/reddwaf-translate-plugin/src/popup/index.ts.
    at makeSourceMapAndFinish (/frontend/reddwaf-translate-plugin/node_modules/ts-loader/dist/index.js:52:18)
    at successLoader (/frontend/reddwaf-translate-plugin/node_modules/ts-loader/dist/index.js:39:5)
    at Object.loader (/frontend/reddwaf-translate-plugin/node_modules/ts-loader/dist/index.js:22:5)

ERROR in /frontend/reddwaf-translate-plugin/src/popup/index.ts
./src/popup/index.ts 2:16-27
[tsl] ERROR in /frontend/reddwaf-translate-plugin/src/popup/index.ts(2,17)
      TS2307: Cannot find module './App.vue' or its corresponding type declarations.
ts-loader-default_0c5a263502dc9404

webpack 5.67.0 compiled with 2 errors in 955 ms

this is my package.json:

{
  "name": "reddwaf-translate-plugin",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "rm -rf src/bundle && webpack --mode development --config src/resource/config/webpack.dev.config.js",
    "build": "gulp --cwd . --gulpfile build/gulp-build.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/jiangxiaoqiang/reddwaf-translate-plugin.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/jiangxiaoqiang/reddwaf-translate-plugin/issues"
  },
  "homepage": "https://github.com/jiangxiaoqiang/reddwaf-translate-plugin#readme",
  "devDependencies": {
    "@babel/core": "^7.16.12",
    "@babel/preset-env": "^7.16.11",
    "babel-loader": "^8.2.3",
    "copy-webpack-plugin": "^10.2.1",
    "html-webpack-plugin": "^5.5.0",
    "mini-css-extract-plugin": "^2.5.3",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.5",
    "webpack": "^5.67.0",
    "webpack-cli": "^4.9.2"
  },
  "dependencies": {
    "@types/chrome": "^0.0.177",
    "@types/webextension-polyfill": "^0.8.2",
    "vue": "^3.2.29",
    "vue-loader": "^15.9.8",
    "vuex": "^4.0.2"
  }
}

and this is the webpack config:

const path = require('path');
const webpack = require( 'webpack' );
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin');
const HtmlWebpackPlugin = require( 'html-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  entry : {
    'popup/popup' : './src/popup/' 
  } ,
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
    alias: {
        vue: 'vue/dist/vue.esm-bundler.js'
    },
  },
  output : {
    path : path.resolve(__dirname, '../../bundle') ,
    filename : '[name].js'
  },
  module : {
    rules : [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/]
        },
        exclude: /node_modules/
      },
      
      {
        test : /\.js$/ ,
        exclude : [ /node_modules(?!(\/|\\?\\)(translation\.js|selection-widget|connect\.io|chrome-env)\1)/ ] ,
        loader : 'babel-loader'
      } ,
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      {
        test : /\.(scss)$/ ,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
      }
    ]
  },
  plugins : [
    new CopyPlugin({
      patterns: [
        { from: "src/manifest.json", to: "manifest.json" },
        { from: "src/resource/image", to: "resource/image" },
      ],
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
    new HtmlWebpackPlugin({
      filename: 'popup/popup.html',
      template: 'src/popup/index.html'
    }),
    new webpack.DefinePlugin({
      __VUE_OPTIONS_API__: false,
      __VUE_PROD_DEVTOOLS__: false,
    }),
  ]
};

2 Answers 2

42

Try placing the following in a src/shims-vue.d.ts file:

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}
Sign up to request clarification or add additional context in comments.

4 Comments

No idea how it worked, but it worked. Thank you sir.
Can you please explain how this works? Thank you.
About this matter, someone already shared a light about it here: stackoverflow.com/a/59788563/1214237
i am using webstorm, this solution worked, but i don't know why, thank you
4

About the previous answer, someone already shared a light about it here.

But I've found also that it was a specific problem in Vue + Typescript projects in VSCode. If you're using Volar that is the official plugin for Vue 3 instead Vetur and using typescript in your project, you need also Typescript Vue Plugin (Volar).

Sharing it because that solved my IDE issue. Nothing was wrong with the project, which even with red mark, it was running without any error or warning.

1 Comment

Is the Typescript Vue Plugin also available for the typescript-language-server on Linux or vim-lsp? A workaround seems to be to define a shim file but that effectively disables linting so that's not really a solution. It just removes the error in the editor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.