Inject JavaScript files inside Templates or HTML with webpack

510
February 13, 2020, at 04:40 AM

Let's say I have a server (Node & Express for example) which serves HTML pages to clients based on templates files (as pug, ejs, handlebars, twig, marko...). It's a classical multi pages website where each page has it's own JavaScript files. If I use webpack to bundle JavaScript files, is it possible to inject automatically (with the build step) Javascript files into their corresponding templates ?

I don't want to generate HTML files, so every html-webpack-plugin based solutions are not what i am searching. I want to do like i can do with grunt or gulp, but with webpack to don't have to import each bundle manually in each corresponding template.

Example of solutions without webpack :

gulp inject

post build

I don't find real answers in other posts.

Thank you in advance.

Edit

It kind of works. I tried with pug and then with marko based on SpeedOfRound answer. I had a problem to inject files because my templates are nested (layout, wrapper, page...) and i didn't have head or body in files where i wanted to place my tags. I used inject: false and <%= htmlWebpackPlugin.tags.bodyTags %> (only available in v4.0 +) and it works, but not exactly what i expected. Here we are creating a new file in ./dist/ and not in the same place of the original file (blocked by path). I just want to make a bundle by template and inject it in the right template automatically.

After, the final goal would be to just create JS files in the right folder where a template view lives and then it would be automatically inject to this view (in the convention over configuration way).

Answer 1

You can do this with HtmlWebpackPlugin by pointing it to your template. Heres my abridged webpack.config.js where I do this with mustache templates.

const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: {
    entry: "./js/app.js",
  },  
  output: {
    path: path.join(__dirname, 'dist'),
    filename: "[name].js",
    chunkFilename:'[name].[chunkhash].js',
    publicPath: '/dist/'
  },
  plugins: [
    new webpack.ProvidePlugin({
      'React': 'react',
    }),
    new HtmlWebpackPlugin({
      inject: 'head',
      filename: path.resolve(__dirname, './templates/dist/app.mustache'),
      template: path.resolve(__dirname, "./templates/app.mustache"),
      chunks: ['entry'],
      favicon: "./public/favicon.ico"
    }),
  ]
}

This is very useful for code splitting, where you can split your builds into chunks and inject multiple chunks into your pages. That way you can reuse chunks and the browser only has to load them once between pages.

It dosn't have to be mustache, I also do this with php views.

READ ALSO
How do I override a JQuery (Datatable RowGroup) library function?

How do I override a JQuery (Datatable RowGroup) library function?

I'm rather new to Javascript, and the scoping syntax definitely confuses me when looking at open source libraries especially when it has a lot of advanced concepts like closure, anonymous functions, etcThe Jquery Datatables RowGroup is a a bit buggy with Responsiveness,...

509
How to fix 401 after attempt to override existing POST?

How to fix 401 after attempt to override existing POST?

I'm receiving 401 error when trying to override existing POST with new dataIt throws 401

3267
Dynamic Object Reference in Object.keys(obj) [duplicate]

Dynamic Object Reference in Object.keys(obj) [duplicate]

How can I iterate through an ObjectKeys(obj) where the obj might change (and thus need to be a variable that changes)?

475
Accessing A Block By Clicking A Button

Accessing A Block By Clicking A Button

I have a form in my webpage and I have created a button in the footer area of my pageI wants if anyone clicks this button then they will go to the contact form which is located on the top of my page

476