Webpack: import TypeScript module both "normally" and as raw string
Asked Answered
D

6

18

Using webpack ^v2.2.1, I would like to import a TypeScript module as text, in addition to importing the same module "normally".

I've figured that I probably should use the raw-loader. But it isn't working out.

Some example code:

import DemoComponent from './demo'
import demoCode from 'raw-loader!./demo'

TypeScript is screaming at me that something like

error TS2307: Cannot find module 'raw-loader!./demo'.

I'm using ts-loader.

Here is my webpack.config.js:

const { resolve } = require('path')
const fail = require('webpack-fail-plugin')

const config = {
  entry: './docs/index.ts',
  output: {
    filename: 'bundle.js',
    path: resolve(__dirname, 'docs-build')
  },
  resolve: {
    extensions: [ '.ts', '.js' ]
  },
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js$/,
        loader: 'source-map-loader'
      },
      {
        test: /\.ts$/,
        loader: 'ts-loader'
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          },
          'sass-loader'
        ]
      }
    ]
  },
  plugins: [
    fail
  ]
}

module.exports = config
Diploblastic answered 6/3, 2017 at 17:15 Comment(1)
Related #33916430Swint
D
24

In case anyone is searching for a solution to this answer. Using import is the best option - it will be typed and allow optimizations from module bundlers like Rollup and Webpack 3+ when outputting import vs require:

You need to create a raw-loader.d.ts and make sure it is included by your tsconfig.jsonfile. Enter the following contents:

declare module '!!raw-loader!*' {
  const contents: string
  export = contents
}

tsconfig.json:

{
    "compilerOptions": {
        "types": ["raw-loader.d.ts", "node"]
    }
}
Deflection answered 12/3, 2018 at 13:3 Comment(2)
what does it mean if we get "Cannot find type definition file for raw-loader.d.ts" even though that file is present in the same folder?Acorn
@Andy, just don't add anything extra into the tsconfig.json. Just the file .d.ts is anough.Paxwax
D
3

It seems that the following is working:

import DemoComponent from './demo'
const demoCode = require('!!raw-loader!./demo')

But I'm not sure how correct this is. I would love to find some documentation about the order and mechanism of loaders.

Also, I would prefer to be consistent, by using import statements, instead. But TypeScript is complaining about it if I do a straight conversion:

import DemoComponent from './demo'
import demoCode from '!!raw-loader!./demo'

The error is a simple

error TS2307: Cannot find module '!!raw-loader!./demo'.
Diploblastic answered 6/3, 2017 at 18:40 Comment(1)
I happen to be enjoying the benefit of require's runtime nature, in this case, so I'm going to stick with it.Salpingectomy
W
2

I've written a full explanation about it here: https://yonatankra.com/how-to-solve-ts2307-cannot-find-module-when-using-inline-webpack-loaders-with-typescript/

In summary:

You can import using this syntax: import template from 'raw-loader!./component.template.html';

For this to work for any type of file you'd need to:

  1. Setup a module declaration: raw-loader.d.ts
declare module '!!raw-loader!*' {
  const contents: string
  export default contents
}
  1. Use it in your tsConfig.json and add the allowSyntheticDefaultImports property to allow modules without a default export to be imported this way:
{
  "compilerOptions": {
    "types": ["raw-loader.d.ts", "node"],
    "allowSyntheticDefaultImports": true
}

In the article I also explain how to make this work if (for some truly bizarre reason) you'd like to use template.default.

Wallis answered 8/9, 2021 at 6:33 Comment(0)
P
1

The raw-loader appears to be deprecated with Webpack 5, they recommend configuring the built-in asset/source instead. The following is what worked for me:

in webpack config:

module: {
  rules: [
    {
      resourceQuery: /raw/,
      type: 'asset/source'
    }
  ]
}

raw-asset-source.d.ts

declare module '*?raw' {
  const rawFileContent: string
  export default rawFileContent
}

then you can do imports like

import demoCode from './demo?raw'

and demoCode should be a string containing the contents of the file

Pigskin answered 30/8, 2023 at 7:46 Comment(0)
P
0

For your error:

raw-loader.d.ts:

declare module '!!raw-loader!*' {
  const contents: string
  export default contents
}
Psychodiagnosis answered 7/6, 2019 at 0:32 Comment(0)
L
0

For me, removing the "!!" from @Nicolas's answer works

declare module 'raw-loader!*' {
  const contents: string
  export default contents
}

I don't have the time to dive in but just in case someone needs it. I'm using [email protected] & [email protected]

Loopy answered 3/7, 2023 at 10:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.