webdiscus / html-bundler-webpack-plugin

Alternative to html-webpack-plugin ✅ Renders Eta, EJS, Handlebars, Nunjucks, Pug, Twig templates "out of the box" ✅ Resolves source files of scripts, styles, images in HTML ✅ Uses a template as entry point
ISC License
146 stars 15 forks source link

[QUESTION] Include javascript file generated by babel-loader/ts-loader #98

Closed R1kk3r closed 4 months ago

R1kk3r commented 4 months ago

I have an index.ts and because I am targeting super old browsers, I need to:

I would like to use HtmlBundlerPlugin but I cannot figure out how to tell him to include the resulting main.js. Doing something like this

<script src="dist/main.js"r></script>

will return the following error

...
HTML Bundler Plugin  Resolving of source files in the template file failed.
File: src/views/mytemplate.eta
Error: Cannot find module '/Users/xxx/yyy/ccc/repo/dist/main.js'

It seems everything is generated at the same time and the main.js is not yet outputted into /dist/.

Any idea how I can fix this?

My current webpack config generating the main.js.

entry: ['whatwg-fetch', './src/index.ts'],
resolve: {
  extensions: [ '.ts', '.js'],
},
module: {
    rules: [
     {
         test: /\.js$/,
         include:[
             /node_modules\/\@aaaa/,
             /node_modules\/\@bbbb/,
         ],
         use: [{
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', { targets: "chrome 37", useBuiltIns: "usage", modules:"cjs", corejs:3, debug:false}]
            ]
          }
        }]
     },
      {
        test: /\.ts$/,
        exclude: [
          path.resolve(__dirname, 'tests')
        ],
        use: [{
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', { targets: "chrome 37", debug:false}]
            ]
          }
        },
        {
        loader: 'ts-loader',
        }
     ]
    }
    ],
  },
  target: ['es5', 'web'],
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
webdiscus commented 4 months ago

@R1kk3r

you should specify the source ./src/index.ts file directly in the template using the relative path or webpack alias:

<script src="./index.ts"></script>

You you need to create a bundle with many source files, then do it in one JS/TS file, not in webpack: ./src/main.js

import 'whatwg-fetch';
import 'index.ts';

then define this source ./src/main.js in template ./src/views/mytemplate.eta:

<!-- the ../main.js path is relative to the ./src/views/mytemplate.eta -->
<script src="../main.js"></script>

The plugin resolves source files of assets (SCSS, TS/JS, etc.) in templates and replaces them with correct output URLs in the generated HTML.

Don't needed to define source TS files in webpack entry.

const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

module.exports = {
  // entry: ['whatwg-fetch', './src/index.ts'], // <= don't define source files here
  resolve: {
    extensions: ['.ts', '.js'],
  },
  plugins: [
    new HtmlBundlerPlugin({
      entry: {
        index: './src/views/mytemplate.eta', // => generates dist/index.html
      },
      js: {
        // define the output name of a generated JS file here
        filename: 'js/[name].[contenthash:8].js',
      },
      css: {
        // define the output name of a generated CSS file here
        filename: 'css/[name].[contenthash:8].css',
      },
    }),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [/node_modules\/\@aaaa/, /node_modules\/\@bbbb/],
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  { targets: 'chrome 37', useBuiltIns: 'usage', modules: 'cjs', corejs: 3, debug: false },
                ],
              ],
            },
          },
        ],
      },
      {
        test: /\.ts$/,
        exclude: [path.resolve(__dirname, 'tests')],
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [['@babel/preset-env', { targets: 'chrome 37', debug: false }]],
            },
          },
          {
            loader: 'ts-loader',
          },
        ],
      },
    ],
  },
  target: ['es5', 'web'],
  output: {
    // filename: 'main.js', // <= don't define a fix filename
    path: path.resolve(__dirname, 'dist'),
  },
};

You can create a small repo with your setup and I will help you to configure it.

R1kk3r commented 3 months ago

The inputs/outputs are not always easy to understand with webpack, multiples rules and plugins. With your solution, it worked just fine, thank you ! To avoid having to include "whatwg-fetch" manually, I used the ProvidePlugin to inject it transparently.