aurelia / bootstrapper-webpack

A custom bootstrapper for using Webpack with Aurelia
MIT License
8 stars 6 forks source link

Aurelia application fails to load with latest Webpack release #16

Closed mdurling closed 7 years ago

mdurling commented 7 years ago

We have an Aurelia app that works fine when built with webpack@2.2.1, however, it will not load when built with webpack@2.3.2. Have you done any verification with the latest webpack release? We are reverting to 2.2.1 for now, but here is the error that is generated when running the latest webpack build:

TypeError: Cannot read property 'call' of undefined
    at __webpack_require__ (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:57:37)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:885:24
From previous event:
    at Promise.then._this2.modulesBeingLoaded.(anonymous function) (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:884:27)
From previous event:
    at WebpackLoader._import (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:870:18)
    at WebpackLoader.loadModule (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:928:17)
    at config (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:17046:19)
    at handleApp (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:17037:10)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:17065:9
From previous event:
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:17062:44
From previous event:
    at run (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:17059:24)
    at Object.<anonymous> (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:17084:1)
    at Object.aurelia-bootstrapper-webpack (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:17085:30)
    at __webpack_require__ (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:57:38)
    at Object.1120 (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:13784:1)
    at __webpack_require__ (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:57:38)
    at 1023.Event.initEvent.cancelable.type (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:149:18)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?4cf3d825e555e0d099bf:152:10
jods4 commented 7 years ago

Thanks for the heads-up. I haven't yet tried 2.3.2.

You opened this issue in bootstrapper-webpack, is this what you're using? You should use regular aurelia-bootstrapper, it was made "universal" a while ago and bootstrapper-webpack only exists as to not break existing builds.

mdurling commented 7 years ago

We are using aurelia-bootstrapper-webpack@1.1.0 and including it in the core bundle. We originally created our application from aurelia/skeleton-navigation and it is used there.

jods4 commented 7 years ago

I did update all the demos in my repo to webpack 2.3.2 and I did not have any issue, so for what it's worth I think that our latest Webpack plugins / runtime do work properly.

@mdurling you are using older stuff that I am not familiar with, so hopefully someone else can chime in here.

mdurling commented 7 years ago

Perhaps you could send me a copy of or a link to the webpack.config you used and your package.json? I can see if we're doing something outdated. Thanks.

jods4 commented 7 years ago

It's not just a version upgrade, it's redesigned Webpack plugins so you'll need to do a few changes to your build and your code.

If you are interested in upgrading I suggest you start by reading about the new plugins here: https://github.com/jods4/aurelia-webpack-build/wiki

There are several working demos config in that repo as well, I just upgraded all of them to Webpack 2.3.2.

mdurling commented 7 years ago

@jods4 @EisenbergEffect I am making good progress converting our application over to the new plugins/runtime. I've replaced aurelia-bootstrapper-webpack with aurelia-bootstrapper, updated to the latest webpack and added all of the necessary PLATFORM.moduleName calls. The application now builds, starts, runs some of our code, but then throws the following exception. Can you provide any insight into what might still be wrong?

Unhandled rejection Error: Error invoking Show. Check the inner error for details.
------------------------------------------------
Inner Error:
Message: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?
Inner Error Stack:
Error: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?
    at validateKey (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16611:11)
    at Container.get (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16808:5)
    at Container.elementContainerGet [as get] (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7321:15)
    at Object.invoke (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16672:31)
    at InvocationHandler.invoke (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16631:166)
    at Container.invoke (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16895:23)
    at ProviderResolver.get (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7266:72)
    at Container.get (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16834:21)
    at Container.elementContainerGet [as get] (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7321:15)
    at HtmlBehaviorResource.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9279:56)
    at applyInstructions (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7423:31)
    at ViewFactory.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7644:7)
    at HtmlBehaviorResource.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9291:39)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9739:16
    at tryCatcher (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:30677:23)
    at Promise._settlePromiseFromHandler (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:28699:31)
End Inner Error Stack
------------------------------------------------

    at validateKey (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16611:11)
    at Container.get (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16808:5)
    at Container.elementContainerGet [as get] (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7321:15)
    at Object.invoke (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16672:31)
    at InvocationHandler.invoke (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16631:166)
    at Container.invoke (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16895:23)
    at ProviderResolver.get (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7266:72)
    at Container.get (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16834:21)
    at Container.elementContainerGet [as get] (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7321:15)
    at HtmlBehaviorResource.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9279:56)
    at applyInstructions (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7423:31)
    at ViewFactory.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7644:7)
    at HtmlBehaviorResource.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9291:39)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9739:16
    at new AggregateError (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:201:11)
    at Container.invoke (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16897:13)
    at ProviderResolver.get (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7266:72)
    at Container.get (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:16834:21)
    at Container.elementContainerGet [as get] (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7321:15)
    at HtmlBehaviorResource.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9279:56)
    at applyInstructions (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7423:31)
    at ViewFactory.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:7644:7)
    at HtmlBehaviorResource.create (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9291:39)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9739:16
From previous event:
    at CompositionEngine.createController (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9738:8)
    at CompositionEngine._createControllerAndSwap (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9700:17)
    at CompositionEngine.compose (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:9786:19)
    at TemplatingEngine.compose (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:10049:36)
    at Aurelia.setRoot (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:33393:19)
    at Object._callee$ (http://localhost.inmotionnow.com:9001/main.bundle.js?ec6cd1f45213217789ec:132983:33)
    at tryCatch (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:645:40)
    at Generator.invoke [as _invoke] (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:880:22)
    at Generator.prototype.(anonymous function) [as next] (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:697:21)
    at fulfilled (http://localhost.inmotionnow.com:9001/main.bundle.js?ec6cd1f45213217789ec:38517:58)
From previous event:
    at step (http://localhost.inmotionnow.com:9001/main.bundle.js?ec6cd1f45213217789ec:38519:124)
    at http://localhost.inmotionnow.com:9001/main.bundle.js?ec6cd1f45213217789ec:38520:9
From previous event:
    at Object.__awaiter (http://localhost.inmotionnow.com:9001/main.bundle.js?ec6cd1f45213217789ec:38516:12)
    at Object.configure (http://localhost.inmotionnow.com:9001/main.bundle.js?ec6cd1f45213217789ec:132962:20)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:15935:27
From previous event:
    at config (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:15930:54)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:15966:12
From previous event:
    at bootstrap (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:15965:24)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:15952:7
From previous event:
    at run (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:15947:59)
    at Object.<anonymous> (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:15972:16)
    at Object.175 (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:15973:30)
    at __webpack_require__ (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:53:30)
    at Object.1256 (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:4935:1)
    at __webpack_require__ (http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:53:30)
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:147:18
    at http://localhost.inmotionnow.com:9001/bootstrap.bundle.js?ec6cd1f45213217789ec:150:10

This is where things start to go wrong:

screen shot 2017-04-01 at 9 08 39 am
jods4 commented 7 years ago

@mdurling doesn't look related to webpack (DI rather) but reminds me a lot of aurelia/pal-browser#17.

Do you have a custom boot sequence? If yes, you must absolutely ensure that aurelia-pal-browser is initialized before any other lib that might use the PAL, aurelia-framework in particular. aurelia-bootstrapper does this right.

mdurling commented 7 years ago

This sounds like it may be related. I'm not sure what you mean by "custom boot sequence" but it's quite probable that we do. On Sat, Apr 1, 2017 at 12:44 PM jods notifications@github.com wrote:

@mdurling https://github.com/mdurling doesn't look related to webpack (DI rather) but reminds me a lot of aurelia/pal-browser#17 https://github.com/aurelia/pal-browser/issues/17.

Do you have a custom boot sequence? If yes, you must absolutely ensure that aurelia-pal-browser is initialized before any other lib that might use the PAL, aurelia-framework in particular. aurelia-bootstrapper does this right.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/aurelia/bootstrapper-webpack/issues/16#issuecomment-290931734, or mute the thread https://github.com/notifications/unsubscribe-auth/ADR8_Uu0wEVjxI3p6OCoR6YKvSllrIBbks5rrn7PgaJpZM4Mr6Xu .

jods4 commented 7 years ago

I mean that the basic way to start Aurelia is to import aurelia-bootstrapper and let it flow from here.

If you load other stuff before that involving Aurelia, it's tricky.

mdurling commented 7 years ago

I added import aurelia-bootstrapper to the top of my main.ts, but that didn't change anything.

On Sat, Apr 1, 2017 at 1:10 PM jods notifications@github.com wrote:

I mean that the basic way to start Aurelia is to import aurelia-bootstrapper and let it flow from here.

If you load other stuff before that involving Aurelia, it's tricky.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/aurelia/bootstrapper-webpack/issues/16#issuecomment-290933569, or mute the thread https://github.com/notifications/unsubscribe-auth/ADR8_QDxbiho70l-LJ28IRzQd3f4966jks5rroUfgaJpZM4Mr6Xu .

jods4 commented 7 years ago

What's your entry point? Is the project visible somewhere?

mdurling commented 7 years ago

Unfortunately, it's a pretty large project currently under development so it's not really visible. Here is our current webpack config. It's more complex than the demo examples:

/// <reference path="./node_modules/@types/node/index.d.ts" />

import * as path from 'path'

// easy-webpack
import { generateConfig, stripMetadata } from '@easy-webpack/core'
import * as envProd from '@easy-webpack/config-env-production'
import * as envDev from '@easy-webpack/config-env-development'
import * as typescript from '@easy-webpack/config-typescript'
import * as html from '@easy-webpack/config-html'
import * as sass from '@easy-webpack/config-sass'
import * as fontAndImages from '@easy-webpack/config-fonts-and-images'
import * as globalBluebird from '@easy-webpack/config-global-bluebird'
import * as globalRegenerator from '@easy-webpack/config-global-regenerator'
import * as generateIndexHtml from '@easy-webpack/config-generate-index-html'
import * as commonChunksOptimize from '@easy-webpack/config-common-chunks-simple'
import * as copyFiles from '@easy-webpack/config-copy-files'
import * as uglify from '@easy-webpack/config-uglify'
import * as generateCoverage from '@easy-webpack/config-test-coverage-istanbul'
import * as json from '@easy-webpack/config-json'

// Plugins
import { AureliaPlugin } from 'aurelia-webpack-plugin'
import * as WebpackNotifierPlugin from 'webpack-notifier'

const ENV: 'development' | 'test' | 'production' = process.env.NODE_ENV && process.env.NODE_ENV.toLowerCase() || (process.env.NODE_ENV = 'development')
const COVERAGE: boolean = false

const bundles = {
  polyfills: [
    'regenerator-runtime',
    'bluebird'
  ],
  aurelia: [
    'aurelia-pal',
    'aurelia-pal-browser',
    'aurelia-binding',
    'aurelia-dependency-injection',
    'aurelia-event-aggregator',
    'aurelia-framework',
    'aurelia-history',
    'aurelia-history-browser',
    'aurelia-loader',
    'aurelia-logging',
    'aurelia-logging-console',
    'aurelia-metadata',
    'aurelia-path',
    'aurelia-polyfills',
    'aurelia-route-recognizer',
    'aurelia-router',
    'aurelia-task-queue',
    'aurelia-templating',
    'aurelia-templating-binding',
    'aurelia-templating-router',
    'aurelia-templating-resources',
    'aurelia-computed',
    'aurelia-validation'
  ],
  formio: [
    'react-formio',
    'react',
    'react-dom'
  ],
  vendor: [
    'query-string',
    'node-uuid',
    'jwt-decode',
    'jquery',
    'auth0-js',
    'axios',
    'immutable',
    'redux',
    'redux-logger',
    'redux-saga',
    'intl-messageformat',
    'select2'
  ],
  jquery: {
    main: 'https://unpkg.com/jquery@3.2.1/dist/jquery.min.js',
    plugins: [
      'https://unpkg.com/select2@4.0.3/dist/js/select2.min.js'
    ]
  }
}

/**
 * Main Webpack Configuration
 */
let config = generateConfig(
  {
    entry: {
      'app': 'aurelia-bootstrapper',
      'vendor': bundles.vendor,
      'aurelia': [
        ...bundles.polyfills,
        ...bundles.aurelia
      ],
      'formio': bundles.formio
    },
    output: {
      path: path.resolve('dist')
    },
    devServer: {
      // Reduce console output when running webpack-dev-server
      stats: {
        colors: true,
        hash: false,
        version: true,
        timings: false,
        assets: true,
        chunks: false,
        modules: false,
        reasons: false,
        children: false,
        source: false,
        errors: true,
        errorDetails: true,
        warnings: true,
        publicPath: false
      }
    },
    plugins: [
      new WebpackNotifierPlugin({ alwaysNotify: true }),
      new AureliaPlugin()
    ],
    resolve: {
      modules: ['src', 'node_modules', ''].map(x => path.resolve(x))
    },
    externals: {
      'jquery': 'jQuery'
    }
  },

  /**
   * Don't be afraid, you can put bits of standard Webpack configuration here
   * (or at the end, after the last parameter, so it won't get overwritten by the presets)
   * Because that's all easy-webpack configs are - snippets of premade, maintained configuration parts!
   *
   * For Webpack docs, see: https://webpack.js.org/configuration/
   */

  ENV === 'production' ? envProd({ /* devtool: '...' */ }) : envDev(ENV !== 'development' ? {} : {devtool: 'inline-source-map'}),

  typescript(ENV !== 'test' ? {} : { options: { doTypeCheck: false, sourceMap: false, inlineSourceMap: true, inlineSources: true } }),

  html(),

  json(),

  sass({ filename: 'styles.css', allChunks: true, sourceMap: false }),

  fontAndImages(),

  globalBluebird(),

  globalRegenerator(),

  generateIndexHtml({
    minify: ENV === 'production',
    overrideOptions: {
      hash: true,
      template: 'aurelia-app.ejs',
      scripts: [
        bundles.jquery.main,
        ...bundles.jquery.plugins
      ]
    }
  }),

  ...(ENV !== 'test'
    ? [
      commonChunksOptimize({appChunkName: 'app', firstChunk: 'aurelia'}),
      copyFiles({
        patterns: [
          { context: 'deploy', from: '*.*', to: '' },
          { context: 'node_modules/seamless/build', from: 'seamless.parent.min.js', to: ''}
        ]
      })
    ]
    : COVERAGE
      ? [
        /* ENV === 'test' */
        generateCoverage({ options: { esModules: true } })
      ]
      : []
    ),

  ENV === 'production' ? uglify({debug: false, mangle: { except: ['cb', '__webpack_require__'] }}) : {}

)

module.exports = stripMetadata(config)
jods4 commented 7 years ago

Well, there is a lot here. You're entry point is aurelia-bootstrapper so that's good.

I am not familiar with @easy-webpack I have some doubts regarding how you build your common/vendor bundles, though. Which file do you load in your HTML index page?

I am wary of your aurelia chunk, because if you load it, then all those modules you have listed are entry points and they will all get executed when this file is loaded. Executing aurelia-framework before aurelia-pal is initialized (and unfortunately this is different from just importing it, see the related issue) is known to create this bug.

This comment might be relevant.

mdurling commented 7 years ago

Thanks. I think I understand how this is supposed to work now and have made some progress. Based on your suggestions, I removed all of the bundling and now have just a single entry aurelia-bootstrapper. I am no longer getting that DI error. The app loads, but now it is throwing an exception because it can't find the module for the initial route even though all of the routes are defined using PLATFORM.moduleName() just like app root, features, globalResources, etc. are which are being found/loaded.

It looks like most of my source files are not being bundled... This is the tail of the webpack --display-modules

[1114] ./~/vm-browserify/index.js 3.8 kB {0} [optional] [built]
[1115] (webpack)/buildin/harmony-module.js 596 bytes {0} [built]
[1116] ./~/whatwg-fetch/fetch.js 12.7 kB {0} [built]
[aurelia-templating-router/router-view] ./~/aurelia-templating-router/dist/native-modules/router-view.js 8.17 kB {0} [built]
[1120] multi aurelia-webpack-plugin/dist/aurelia-entry aurelia-loader-webpack regenerator-runtime bluebird aurelia-bootstrapper 76 bytes {0} [built]
[app] ./src/app.ts 5.51 kB {0} [built]
[app.html] ./src/app.html 1.77 kB {0} [built]
[aurelia-computed] ./~/aurelia-computed/dist/native-modules/aurelia-computed.js 7.72 kB {0} [built]
[aurelia-event-aggregator] ./~/aurelia-event-aggregator/dist/native-modules/aurelia-event-aggregator.js 2.89 kB {0} [built]
[aurelia-framework] ./~/aurelia-framework/dist/native-modules/aurelia-framework.js 14.2 kB {0} [built]
[aurelia-history-browser] ./~/aurelia-history-browser/dist/native-modules/aurelia-history-browser.js 8.95 kB {0} [built]
[aurelia-logging-console] ./~/aurelia-logging-console/dist/native-modules/aurelia-logging-console.js 1.53 kB {0} [built]
[aurelia-pal-browser] ./~/aurelia-pal-browser/dist/native-modules/aurelia-pal-browser.js 14.1 kB {0} [built]
[aurelia-templating-binding] ./~/aurelia-templating-binding/dist/native-modules/aurelia-templating-binding.js 24.1 kB {0} [built]
[aurelia-templating-resources] ./~/aurelia-templating-resources/dist/native-modules/aurelia-templating-resources.js 3.59 kB {0} [built]
[aurelia-templating-resources/attr-binding-behavior] ./~/aurelia-templating-resources/dist/native-modules/attr-binding-behavior.js 439 bytes {0} [built]
[aurelia-templating-resources/binding-mode-behaviors] ./~/aurelia-templating-resources/dist/native-modules/binding-mode-behaviors.js 963 bytes {0} [built]
[aurelia-templating-resources/compose] ./~/aurelia-templating-resources/dist/native-modules/compose.js 6.12 kB {0} [built]
[aurelia-templating-resources/debounce-binding-behavior] ./~/aurelia-templating-resources/dist/native-modules/debounce-binding-behavior.js 1.55 kB {0} [built]
[aurelia-templating-resources/focus] ./~/aurelia-templating-resources/dist/native-modules/focus.js 1.82 kB {0} [built]
[aurelia-templating-resources/hide] ./~/aurelia-templating-resources/dist/native-modules/hide.js 1.1 kB {0} [built]
[aurelia-templating-resources/if] ./~/aurelia-templating-resources/dist/native-modules/if.js 2.78 kB {0} [built]
[aurelia-templating-resources/repeat] ./~/aurelia-templating-resources/dist/native-modules/repeat.js 10.7 kB {0} [built]

My routes appear nowhere in the list. I would expect them at the end with the rest of the named modules, but they're not even in the number modules!

mdurling commented 7 years ago

@jods4 I figured out what was happening. Our route configs are build up functionally and the PLATFORM.moduleName was being called within a function. This makes sense programmatically, but not when you consider that the webpack plugin needs to parse for these things during the build. I moved the PLATFORM.moduleName to where the moduleId string is declared and now it works. Thank you so much for your guidance in getting me to this point. This approach is much more intuitive than the old webpack plugin.

A few other items that I would like your opinion on if you don't mind.

  1. The output.filename property seems to have no affect on the generated bundle. I am getting main.bundle.js regardless of the output.filename setting. I am assuming something else in my config is overwriting it, but I'm not sure. It's not a problem for now, but I think I need to figure it out before I will be able to get any sort of code splitting to work.

  2. What is your recommended approach to bundling vendor modules. Is the ReferenceDll plugin the easiest way to go and just build the vendor module separately?

  3. What is your recommended approach for handling polyfills? Should they just be put in the main entry along with aurelia-bootstrapper, or should they be bundled separately?

  4. I get a couple of strange errors when running our unit tests in karma:

    WARN: '%cWarning: a promise was rejected with a non-error: [object String]
    at createLoader (http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:6109:18)
    From previous event:
    at run (http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:6180:18)
    at Object.<anonymous> (http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:6205:16)
    at Object.107 (http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:6206:30)
    at __webpack_require__ (http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:20:30)
    at Object.1021 (http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:5948:1)
    at __webpack_require__ (http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:20:30)
    at 0.Object.defineProperty.value (http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:66:18)
    at http://localhost:9876/base/spec-bundle.js?f3f47cd492939a195d954d7e7e9d6bc0db107141:69:10'

and

Unhandled rejection No PLATFORM.Loader is defined and there is neither a System API (ES6) or a Require API (AMD) globally available to load your app.'

I am glad I've invested the time to convert our project over. I like the new bootstrap approach much better. Thanks again.

jods4 commented 7 years ago

Glad you figured it out!

As for your questions:

  1. I don't know what happens exactly as your config is complex and uses a lot of easy-webpack magic that I'm not familiar with. output.filename is what drives the output and FWIW Aurelia plugin 2.0 does not touch this setting. Have a look at the doc: https://webpack.js.org/configuration/output/#output-filename, if you have more than one entry point you need to use some patterns.

  2. It kinds of depends on what your goal is. Currently there are 2 main options: ReferenceDll and CommonChunks but they have very different trade-offs. DLL is more complex and disables lots of (size) optimizations (like tree-shaking, exports renaming and more) but it allows for true split compilation (hence faster) and long-term caching. Commons chunk is simpler but -- if we are talking about a vendor bundle and not its true purpose which is putting common modules in separate bundles -- is only good for having parallel downloads at startup and faster HMR. Both works with Aurelia plugin, but if you go for the latter I have two advices: (a) you don't need to list everything... dependencies are transitively brought in, so aurelia-bootstrapper will already bring all the core in the bundle; (b) put the "commons" in a new chunk and include that one in your page, not the vendor entry. As explained above, if you include vendor then all you've listed as entry points will execute and at the moment this triggers the DI bug. More info about DLL if you intent to use is: https://github.com/jods4/aurelia-webpack-build/wiki/Using-Webpack-DLL

  3. I am thinking about this at the moment. I think I will do a plugin to help as well. The tricky part with polyfills is that they have to execute before anything else, at least if they are required by Aurelia itself (e.g. Promise, MutationObserver, ...). And that is more tricky then it looks. One easy way to handle it is to have one bundle with all your polyfills as entry points, and putting that first in the HTML page. Please note that Aurelia injects some stuff in your main entry point, if you have several it assumes that it is the first one, otherwise you can pass entry: "name" to clarify.

  4. The first error is not telling a lot. The second is more concerning, it seems that aurelia-loader-webpack is not used. Normally it's added automatically to your app entry point (see 3). I am not sure how you build your tests / what happens here.

mdurling commented 7 years ago

Update: I have everything working now. After experimenting with various common chunks scenarios which I eventually got to work, I decided the benefit wasn't worth the maintenance overhead. I had to sort the entry points manually because we are using an ejs template and a webpack plugin to generate our index.html file and then exclude the bundle containing the code I don't need. It's just so much simpler to use aurelia-bootstrapper as the lone entry point. All the extra bundle really does is move the bytes around anyway. As for bundle size, I can accomplish the same thing much easier by just using webpack externals. As for my unit tests, I was able to get rid of those errors by pointing the aureliaApp at my spec file instead of main and loading aurelia-polyfills. Thanks again for all of your guidance. While it took me a while to get everything sorted, it was worth the effort. I even tested the Aurelia code splitting feature and it works great too! @eisenbergeffect we're loving Aurelia and the support your team provides. @jods4 went above and beyond.

mdurling commented 7 years ago

@jods4 We have one component that is rather large. It is currently being loaded as follows:

  config.globalResources([
    PLATFORM.moduleName('resources/components/foo')
  ])

This Aurelia component is a wrapper around a ReactJS component and consists of a single foo.tsx file and uses @noView. I have been trying to figure out how to bundle this component separately so that it is lazy loaded, but I have so far been unsuccessful. If I remove the call to globalResources then the code isn't loaded into the app bundle, but adding it to the aurelia.resources section of our package.json file does not cause a separate bundle to get created. I have tried adding the <require> statement back to the view that uses this component both with and without the lazy attribute, but I either get the component included in the app bundle or not at all. I am not sure if the .tsx extension is somehow causing an issue or if I am just doing something incorrectly. I can probably use the common chunks plugin to force webpack to put this component in its own bundle, but that won't accomplish the lazy loading. Any advice you can provide would be appreciated. Thanks!

jods4 commented 7 years ago

aurelia.resources ain't used by the new plugins, it's only there for the 1.x users. lazy on <require> is not supported either, as I have yet to find a scenario where it would make sense. When you load the view, Aurelia has to load the <require> so splitting code here makes no sense.

I am assuming that you are not just after creating multiple files but lazy-loading on-demand for just the routes that need it.

Here's how to do it:

  1. You must use a local resource with <require>. The problem of .globalResources() is that it's immediately loaded at startup so there's no use making a split point here.
  2. Create a split point for the routes that use your heavy component. The second parameter to moduleName is an optional chunk name, so in your routes config do something like: module: PLATFORM.moduleName('module-that-use-react', 'arbitrary-chunk-name').

Because dependencies are precisely traced, the <require>'d component will go along with the view.

mdurling commented 7 years ago

@jods4 Thanks for the reply. That matches what I have found. I was able to get the global resource into its own chunk, but it was being loaded at startup which defeated the whole purpose. I removed it from the global resources, added a local resource require, and added a chunk name to the route that is using it and I get the desired behavior. Thanks again. It would be good at some point to update the Webpack section of the docs at aurelia.io as they still describe the old manner of using Webpack. The new plugins and runtime have been working great for us since making the switch. Cheers, Michael

narmstrong1988 commented 7 years ago

@mdurling Could you give an example of how you got your unit tests working. I am getting the same platform.loader issue you mentioned above?

mdurling commented 7 years ago

@narmstrong1988 Are you doing a require('aurelia-bootstrapper') in your spec-bundle file? In our setup, I fixed the error messages by replacing require('aurelia-bootstrapper') with require('aurelia-polyfills') but it likely depends on how you are creating your spec bundle. Our tests were passing in both cases, but the latter eliminated the errors we were seeing in the logs. Hope this is helpful.

bhalperin commented 7 years ago

I have a small Aurelia app and just upgraded Webpack to version 3 without any code changes. The app fails to load with this message:

Uncaught (in promise) No PLATFORM.Loader is defined and there is neither a System API (ES6) or a Require API (AMD) globally available to load your app.

Update: I upgraded html-webpack-plugin to 2.29.0 - the latest at this time - and all is back to normal.