damianstasik / vue-svg-loader

🔨 webpack loader that lets you use SVG files as Vue components
https://vue-svg-loader.js.org
MIT License
645 stars 86 forks source link

Typescript Cannot find module '@/assets/svg/register.svg?inline' #92

Open avxkim opened 5 years ago

avxkim commented 5 years ago

Created svg.d.ts file with the following contents:

declare module '*.svg' {
  const content: any
  export default content
}

Then using in a component this way:

import register from '@/assets/svg/register.svg?inline'

Causes an error: Typescript Cannot find module '@/assets/svg/register.svg?inline'

But if i remove ?inline it stops complaining. How to correctly declare svg module in .d.ts file?

FlorianWerndl commented 5 years ago

@webcoderkz did you find a solution for that meanwhile?

avxkim commented 5 years ago

@FlorianWerndl i just abandoned this module.

sergamers commented 5 years ago

I've same problem.

sergamers commented 5 years ago

@webcoderkz @maximelafarie I solve it that:

Create in the root next file custom.d.ts:

declare module "*.svg?inline" {
  const content: any;
  export default content;
}

and add to tsconfig.json:

...
"files": ["custom.d.ts"],
...
avxkim commented 5 years ago

Well, using both declaration is the key, as @sergamers previously noted:

declare module '*.svg?inline' {
  const content: any
  export default content
}

declare module '*.svg' {
  const content: any
  export default content
}

But you don't need to add it in tsconfig.json under files, it would be read automatically, you to just name it, like (random name).d.ts

hipkiss91 commented 5 years ago

I'm facing the same issue when running npm run test:unit using the jest framework through vue-cli. It doesn't like the ?inline and it also doesn't like things like import 'pickerjs/dist/picker.css';

batmanhit commented 4 years ago

HI, I am also having an issue whit running jest for ?inline usage.

https://github.com/visualfanatic/vue-svg-loader/blob/master/docs/faq.md#how-to-use-this-loader-with-jest

I have followed this guideline and here is my jest configuration for your information.

module.exports = {
  moduleFileExtensions: [
    'js',
    'jsx',
    'json',
    'vue',
    'ts',
    'tsx'
  ],
  transform: {
    'snippets\/(?!index)': 'jest-raw-loader',
    '^.+\\.vue$': 'vue-jest',
    '^.+\\.jsx?$': 'babel-jest',
    '^.+\\.svg\?inline$': '<rootDir>/test/unit/svgTransform.js',
    '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
    '^.+\\.tsx?$': 'ts-jest'
  },
  transformIgnorePatterns: [
    '/node_modules/'
  ],
  moduleNameMapper: {
    '^vue$': 'vue/dist/vue.common.js',
    '^@/(.*)$': '<rootDir>/src/$1',
    '^test/(.*)$': '<rootDir>/test/$1',
    '^.+.svg\?inline$': '<rootDir>/src/$1',
    '^.+.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub'
  },
  snapshotSerializers: [
    'jest-serializer-vue'
  ],
  testMatch: [
    '**/test/unit/**/*.test.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)',
    '**/test/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
  ],
  testURL: 'http://localhost/',
  verbose: true,
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname'
  ],
  globals: {
    'ts-jest': {
      babelConfig: true
    }
  },
  setupTestFrameworkScriptFile: '<rootDir>test/unit/setupTests.ts',
  setupFiles: ['jest-date-mock']
}

<rootDir>/test/unit/svgTransform.js , this file is where I have located the following code.

const vueJest = require('vue-jest/lib/template-compiler')

module.exports = {
  process (content) {
    console.log('svg transformer', content)
    const { render } = vueJest({
      content,
      attrs: {
        functional: false
      }
    })

    return `module.exports = { render: ${render} }`
  }
}

Here is my shims-svg.d.ts file.

declare module '*.svg?inline' {
  import Vue, { VueConstructor } from 'vue'
  const content: VueConstructor<Vue>
  export default content
}

Also, here is part of my vue.config.js file. I am not using babel-loader so have not added it here.

chainWebpack: config => {
    const svgRule = config.module.rule('svg')
    svgRule.uses.clear()
    svgRule
      .oneOf('inline')
      .resourceQuery(/inline/)
      .use('vue-svg-loader')
      .loader('vue-svg-loader')
      .options({
        svgo: {
          plugins: [
            { prefixIds: true },
            { removeViewBox: false }
          ]
        }
      })
      .end()
      .end()
      .oneOf('external')
      .use('file-loader')
      .loader('file-loader')
      .options({
        name: 'assets/[name].[hash:8].[ext]'
      })
  }

I am getting this error.

image

@hipkiss91, did you manage to resolve the issue?

Please advise on this. Thanks.

KingWu commented 4 years ago

Just find a solution on this issue.

First, by using jest moduleNameMapper function, remove ?inline

moduleNameMapper: {
  '^.+/(.*\\.svg)\\?inline$': '<rootDir>/path/svg/$1'
},

For my case

import SvgBack from '../../assets/svg/back.svg?inline'

(Convert to) ---> 
import SvgBack from '../../assets/svg/back.svg'

Second, transform the svg files into vuejs format

transform: {
    '^.+\\.svg$': '<rootDir>/svgTransform.js',
},

svgTransform.js can find it in the guide https://github.com/visualfanatic/vue-svg-loader/blob/master/docs/faq.md#how-to-use-this-loader-with-jest

jest.config.js

module.exports = {
  collectCoverage: false,
  collectCoverageFrom: [
    '<rootDir>/components/**/*.vue',
    '<rootDir>/pages/*.vue',
  ],
  // tell Jest to handle `*.vue` files
  moduleFileExtensions: [ 'js', 'json', 'vue' ],
  moduleNameMapper: {
    '^.+/(.*\\.svg)\\?inline$': '<rootDir>/assets/svg/$1',
  },
  modulePaths: [ '<rootDir>' ],
  snapshotSerializers: [ '<rootDir>/node_modules/jest-serializer-vue' ],
  transform: {
    // process `*.vue` files with `vue-jest`
    '.*\\.(vue)$': '<rootDir>/node_modules/vue-jest',
    // process js with `babel-jest`
    '^.+\\.js$': '<rootDir>/node_modules/babel-jest',
    // process svg with svgTransform.js
    '^.+\\.svg$': '<rootDir>/tests/tools/svgTransform.js',
  },
  watchman: false,
}
japboy commented 3 years ago

any updates? i still have this issue


svgTransform.js doesn't seem to be necessary any more with vue-jest@4.x. just add vue-jest for the .svg transformer.

module.exports = {
  moduleNameMapper: {
    '^(.*\\.svg)\\?inline$': '$1',
  },
  transform: {
    '\\.svg$': 'vue-jest',
    '\\.vue$': 'vue-jest',
  },
}

this transformer works with vue-jest@4.x:

const compiler = require('vue-template-compiler')

module.exports = {
  process(content) {
    const { render } = compiler.compileToFunctions(content)
    return `module.exports = { render: ${render} }`
  },
}
Tryd0g0lik commented 9 months ago

@sergamers is author message - Thanks

I'm have this problem. webpack5 has an option called alias of setting resolve. Note. The Webpack file is not a solution by error. It is simply an one file from common stack

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = {
  resolve: {
    plugins: [new TsconfigPathsPlugin()]
  },

  resolve:{
    alias:{
      '@Img': path.resolve(__dirname, 'src/img'),
      '@Root': path.resolve(__dirname, 'src/interfaces.ts'),
      '@Pages': path.resolve(__dirname, 'src/components/pages')

    }
  }
}

quote of a Doc.:

Now, instead of using relative paths when importing like so: js import Utility from '../../utilities/utility'; you can use the alias: js import Utility from 'Utilities/utility';

i have files:

// interfaces.ts
export interface Child {
  children: JSX.Element
}
// index.tsx
import { Child } from '@Root';
/// No need to find the "@Root" module or its associated .ts type declarations(2307)
// and 
import { PagesFC } from '@Pages/Pages.tsx'; // is also with error

and

/// custom.d.ts

declare module '@Img/*' { // this option is working
  const content: string;
  export default content;
}

declare module '@Root' { // this options return error presented above
  const content: any; // or string
  export default content;
}

Then '@Root' is remove from custom.d.ts After, i inserted options in tsconfige.json:

"baseUrl": "./",
"paths": {
      "@Root": [
        "src/frontend/src/interfaces.ts",
      ],
     "@Pages/*": [
        "./src/frontend/src/components/pages/*"
      ]
    }

And file index.tsx (below) receives the import without errors

// index.tsx
import { Child } from '@Root';
// or
import { PagesFC } from '@Pages/Pages.tsx';

custom.d.ts file created too. It's for imports the '@Img/*'

// Page/index.tsx

import headerLogo from '@Img/header-logo.png';