Jonathan Cowling
Jonathan Cowling

Reputation: 555

Configuring Typescript to work with html modules

I'm trying to set up a project using typescript and webpack, however I'm unable to bundle html files during the build process.

I'm expecting index.ts to import all .html files as strings (it can import .ts files just fine), this will then cause webpack to bundle them using file-loader and place them in dist/examples (so if I had more .html files I would import them here and they'd end up in dist/examples too).

I have tried both relative and absolute names for the import, but I get the error TS2307: Cannot find module './file.html' when run with both webpack and when I try and do it manually with tsc -p src/tsconfig.json.

I'm fairly new to typescript and this is the first time I've worked with .d.ts files but from what I understand the index.d.ts file should tell typescript to resolve all .html files as strings.

webpack.config.js

const path = require('path');

module.exports = {
  mode: 'development',
  entry: {
    main: path.resolve(__dirname, 'src', 'main', 'index.ts'),
    html: path.resolve(__dirname, 'src', 'res', 'html', 'index.ts')
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/,
        options: {
          configFile: 'src/tsconfig.json',
        }
      },
      {
        test: /\.html$/,
        loader: 'file-loader',
        include: path.resolve(__dirname, 'src', 'res', 'html'),
        exclude: /node_modules/,
        options: {
          name: '[name].[ext]',
          outputPath: 'examples',
        }
      }
    ]
  },
  resolve: {
    extensions: [ '.ts', '.html', '.js' ]
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist')
  }
};

src/tsconfig.json

{
  "compilerOptions": {
    "outDir": "../dist/",
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es5",
    "allowJs": false,
    "moduleResolution": "node",
    "lib": ["es6", "dom"],
    "typeRoots": [ "../node_modules/@types", "../types"],
  },
  "include": [
        "main/**/*",
        "res/html/**/*"
    ],
    "exclude": []
}

types/index.d.ts

declare module '*.html' {
  const value: string;
  export default value
}

src/res/html/index.ts

import test from './test'
import file from './file.html'

src/res/html/file.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>FILE</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <h1>hello world</h1>
</body>
</html>

Upvotes: 3

Views: 8304

Answers (1)

Paleo
Paleo

Reputation: 23702

Your directory "types/" includes a file with the following content:

declare module "html!*" {
    const value: string
    export default value
}

This directory must be accessible from the included paths (the option "include" in the file tsconfig.json).

Notice that the "typeRoots" option should not be used to include your own types. It is the option to make the TypeScript compiler mechanism configurable when it uses the @types system of npm.

Upvotes: 5

Related Questions