Maverik Minett
Maverik Minett

Reputation: 2452

Webpack: Generate index.html for use with Django

I have an Angular 4/Django application, all of the angular code in a Django application. The angular app is built using webpack.

I would like webpack to output the .js bundles into the "static" folder and an "index.html" file into the "templates" folder. The <script></script> tags that are injected will also need to be updated to use Django's "static files" notation:

{% load static %}

<script type="text/javascript" src="{% static 'dist/polyfills.js' %}"></script>

Here is my directory structure (some files omitted for brevity), where project is the top-level holding the Django project.

project
    + angular
        + app (angular application root)
            + config
            + node_modules
            + src
            - webpack.config.js
        + static
            + dist ( webpack output folder)
                - app.[hash].js
                - vendor.[hash].js
                - polyfills.[hash.js
                - index.html
        + templates
                - index.html 

For clarification. Here is my current "templates/index.html" file that is served by Django. This works fine as it is. I would like to have webpack generating this file if possible because I want to use the [hash] in the naming of the dis files and have that updated automatically here. So I would have app.[hash].js, vendor.[hash].js, polyfill.[hash].js and the Django template would be updated when my angular app is built by webpack.

templates/index.html

    {% load static %}
    <html>
      <head>
          <base href="/">
        <title>App</title>
        <link href="{% static 'dist/app.css' %}" rel="stylesheet">
      </head>
      <body>

        <my-app>Loading...</my-app>


       <script type="text/javascript" src="{% static 'dist/polyfills.js' %}"></script>
       <script type="text/javascript" src="{% static 'dist/vendor.js' %}"></script>
       <script type="text/javascript" src="{% static 'dist/app.js' %}"></script>

    </body>

</html>

Upvotes: 3

Views: 1851

Answers (1)

djangulo
djangulo

Reputation: 96

Webpack uses the html-webpack-plugin to generate the templates. I've found a workaround (it feels hacky, and it's certainly an extra layer of work) which uses the webpack.config.js along with the django templates.

Note that Angular2/4/5/whatever doesn't give you access to its webpack config. Use ng eject (See this answer) to extract it. The webpack.config.js below is an excerpt with modifications.

DISCLAIMER I've only ever used this with a Webpack + Django project. Changing the default Webpack config for Angular2 seems like a huge rabbit hole to go into. I would suggest avoiding this and using Django Rest Framework + Angular2 to completely separate the back-end from the front-end. But to each its own i guess; below is my solution:

// webpack.config.js
// ...
const HtmlWebpackPlugin = require('html-webpack-plugin'); // should already be here,
                                            // but it's the main player of this excerpt

module.exports = {
    // ...
    "entry": {
        "main": ["./src/main.ts"],
        "polyfills": ["./src/polyfills.ts"],
        "styles": ["./src/assets/css/styles.css"]
    },
    "output": {
        "path": path.join(process.cwd(), "dist"),
        "filename": "[name].bundle.js",
        "chunkFilename": "[id].chunk.js",
        "publicPath": '/'             // <- this is new
    },
    // ...
    "plugins": [
        // ...
        new HtmlWebpackPlugin({
            "template": "./templates/index.html", // <- path to your template
            "filename": "./path/of/output/file.html", // <- output html file
                                              // default  is './index.html'
            "inject": false // <- this allows you to place the static files
                            //    where you want them
     // ...

Then

# my_project.settings.py
# ...
# assuming your angular and django projects share the same base dir
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'src'), # <- this is webpack's output dir
)

Then in your template

<!-- templates/index.html -->
{% load static %}
<html>
  <head>
    <base href="/">
    <title>App</title>
    <link href="{% static 'dist/app.css' %}" rel="stylesheet">
  </head>
  <body>
    <my-app>Loading...</my-app>
    <script type="text/javascript" src="{% static '<%= htmlWebpackPlugin.files.chunks.polyfills.entry' %}"></script>
    <script type="text/javascript" src="{% static '<%= htmlWebpackPlugin.files.chunks.vendor.entry' %}"></script>
    <script type="text/javascript" src="{% static '<%= htmlWebpackPlugin.files.chunks.app.entry' %}"></script>

  </body>

</html>

You will have to run django's python manage.py collectstatic --clear after every webpack build (in order to clean the 'static' folder).

Upvotes: 4

Related Questions