webdiscus / html-bundler-webpack-plugin

Renders Eta, EJS, Handlebars, Nunjucks, Pug, Twig templates "out of the box". Uses HTML template as entry point. Resolves source files of scripts, styles, images in HTML. Supports for Vue.
ISC License
124 stars 13 forks source link

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

Closed R1kk3r closed 1 week ago

R1kk3r commented 3 weeks 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 3 weeks 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 6 days 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.