Joakim
Joakim

Reputation: 11978

Multiple bundles with Aurelia + Webpack 2

Background

I'm trying to create a project using Aurelia, using Webpack2 for bundling. The code is written using TypeScript. I use Yarn to handle the NPM dependencies.

My webpage is going to consist of multiple core HTML pages. The idea is then to have one Aurelia App for each of these pages.

So the index.html on each of these pages would have a <div aurelia-app="some_module">, each referring to a different module. Each of these are then located in their own bundle. Shared code between them are in separate bundles.

Current config

My directory structure looks as follows:

aurelia-webpack/src/monitor/    # main.ts, app.ts, app.html
aurelia-webpack/src/test/       # main.ts, app.ts, app.html

So to start with I have this Webpack config. My index.html looks like this (The {% static stuff is from Django):

<div aurelia-app="main">
    <p>Loading...</p>
    <script src="{% static "aurelia-webpack/dist/app.js" %}"></script>
</div>

Then I have this config.

webpack.config.js

var path = require('path');
const { AureliaPlugin } = require('aurelia-webpack-plugin');
const { optimize: { CommonsChunkPlugin }, ProvidePlugin } = require('webpack');

module.exports = {
    entry: {
        app: ['aurelia-bootstrapper'],
        vendor: ['bluebird', 'jquery', 'bootstrap'],
    },
    output: {
        filename: "[name].js",
        chunkFilename: "[name].js",
        sourceMapFilename: "[name].js.map",
        publicPath: "/dist/",
        path: path.resolve(__dirname, 'dist')
    },
    resolve: {
        extensions: [".ts", ".js"],
        modules: [
            "src/monitor",
            "node_modules"
        ].map(x => path.resolve(x))
    },
    module: {
        rules: [
            { test: /\.css$/i, use: ["style-loader", "css-loader"] },
            { test: /\.ts$/, loader: "awesome-typescript-loader" },
            { test: /\.html$/, loader: "html-loader" }
        ]
    },
    plugins: [
        new AureliaPlugin(),
        new ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
    })
    ]
}

Result

This works fine with a hello world app for monitor. When I build using Webpack I can see this:

...
[app] ./src/monitor/app.ts 156 bytes {0} [built]
[app.html] ./src/monitor/app.html 57 bytes {0} [built]
[main] ./src/monitor/main.ts 267 bytes {0} [built]
...

And I can load the page fine and it renders as expected.

As you can see I use aurelia-webpack-plugin as well as aurelia-bootstrapper. If I have understood it correctly, the bootstrapper is the one responsible to find the aurelia-app tag on my <div> and injecting the aurelia bits there, based on the module name main that I refer to.

The contents of my main.ts:

import { Aurelia, PLATFORM } from 'aurelia-framework';

export function configure(aurelia: Aurelia)
{
aurelia.use
        .standardConfiguration()
        .developmentLogging();
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app')));
}

Confusion

However, these two are doing some "magic" things that I have a hard time following.

For example I don't understand how the module name is decided. In this case it's main, but I never configure that explicitly. That is somehow done by aurelia-bootstrapper or the aurelia-webpack-plugin?

When reading the WebPack manual on the entry it is a lot clearer: https://webpack.js.org/configuration/entry-context/#entry

Simple rule: one entry point per HTML page. SPA: one entry point, MPA: multiple entry points.

entry: {
home: "./home.js",
about: "./about.js",
contact: "./contact.js"
}

What I want

With all of the above, what I now want is to be able to add more entry points/modules/apps or whatever the correct term is.

I want to be able to create 2 or more index files:

Monitor:

<div aurelia-app="monitor">
    <p>Loading...</p>
    <script src="{% static "aurelia-webpack/dist/monitor.js" %}"></script>
</div>

Test:

<div aurelia-app="test">
    <p>Loading...</p>
    <script src="{% static "aurelia-webpack/dist/test.js" %}"></script>
</div>

each of these having their own bundle/entry point/module/app, how do I configure this with Webpack and Aurelia?

Is the use case for the aurelia-webpack-plugin somehow limited to only one entry point? I've tried adding explicit entries for src/monitor/main.ts and src/test/main.ts but I don't get anything to work properly.

Upvotes: 0

Views: 871

Answers (2)

jcaddy
jcaddy

Reputation: 501

Just to follow up on my comment below. Here are some screenshots of the relevant section in each of my webpack configs.

My Dashboard Page - dashboard.js created by webpack.config.dashboard.js

weback.config.dashboard.js

My Account Page - account.js created by webpack.config.account.js

weback.config.account.js

This does work in my own aspnet core app so I see no reason why it would not for any other framework. You can also keep each "app" specific js file light by creating the vendor.js file and using the Webpack DLL plugin to create a manifest file which the app page scripts can reference.

However, whilst this works I am not sure it is the best way to achieve the results. Since each "page" is a completely independent Aurelia app I can only share state by using some other browser means, e.g. session or local storage. I may look at Aurelia "Features" as a way to split up the apps features - kind of makes sense.

Upvotes: 0

Joakim
Joakim

Reputation: 11978

I found this issue on the aurelia-webpack github project that explains that this is by design: https://github.com/jods4/aurelia-webpack-build/issues/35#issuecomment-302657535

The summary is that one has to use multiple compilations for each entrypoint. Since the config of webpack is JavaScript, these configs can share most of the settings for a base config and then simply import those for each entry point.

See the issue thread for more details and context.

The author clarified on this in the above mentioned thread:

You are correct, the plugin API is designed for single entry point (SPA) first. With steps from that other comment, I see no reason why multiple entry points would not work, but it's hard to figure that out on your own without a deep understanding of how Aurelia+Webpack+the plugin work together. If this is common enough, maybe I should think about adding simpler support for multiple entry points. (There's no plan right now, but why not?)

Upvotes: 1

Related Questions