aurelia / webpack-plugin

A plugin for webpack that enables bundling Aurelia applications.
MIT License
90 stars 36 forks source link

Webpack 5 Support - No PLATFORM.Loader is defined and there is neither a System API (ES6) or a Require API (AMD) globally #173

Closed PodgeHeavin closed 3 years ago

PodgeHeavin commented 3 years ago

I'm submitting a bug report Issue loading PLATFORM.Loader when using new Webpack 5 support

Please tell us about your environment:

Current behavior: Error appears when running locally

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   Promise.then (async)    
  run @ aurelia-bootstrapper.js:140
  77938 @ aurelia-bootstrapper.js:165
  __webpack_require__ @ bootstrap:24
  __webpack_exec__ @ main-c.2f33a18851053…2d32b.bundle.js:785
  (anonymous) @ main-c.2f33a18851053…2d32b.bundle.js:786
  __webpack_require__.O @ chunk loaded:23
  (anonymous) @ main-c.2f33a18851053…2d32b.bundle.js:787
  webpackJsonpCallback @ jsonp chunk loading:557
  (anonymous) @ main-c.2f33a18….bundle.js:1

Expected/desired behavior: No error, app loads as expected

Webpack configuration

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const TerserPlugin = require('terser-webpack-plugin');
const project = require('./aurelia_project/aurelia.json');
const { AureliaPlugin, ModuleDependenciesPlugin } = require('aurelia-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

const webpack = require('webpack');

// config helpers:
const ensureArray = config => (config && (Array.isArray(config) ? config : [config])) || [];
const when = (condition, config, negativeConfig) => (condition ? ensureArray(config) : ensureArray(negativeConfig));

// primary config:
const title = 'Project Central';
const outDir = path.resolve(__dirname, 'dist');
const srcDir = path.resolve(__dirname, 'client-app');
const baseUrl = '/';

module.exports = ({ prod, WEBPACK_SERVE: devServer } = {}, { analyze, tests, hmr, port, host } = {}) => {
  return {
    target: 'web',
    resolve: {
      extensions: ['.ts', '.js'],
      modules: [srcDir, 'node_modules'],
      alias: {
        'aurelia-binding': path.resolve(__dirname, 'node_modules/aurelia-binding'),
        '@data': path.resolve(__dirname, 'client-app/data'),
        '@modules': path.resolve(__dirname, 'client-app/app/modules'),
        '@app': path.resolve(__dirname, 'client-app/app')
      }
    },
    entry: {
      main: ['aurelia-bootstrapper']
    },
    mode: prod ? 'production' : 'development',
    output: {
      path: outDir,
      publicPath: baseUrl,
      filename: '[name].[contenthash].bundle.js',
      sourceMapFilename: '[name].[contenthash].bundle.map',
      chunkFilename: '[name].[contenthash].chunk.js'
    },
    optimization: {
      moduleIds: 'deterministic',
      removeAvailableModules: true,
      concatenateModules: true,
      runtimeChunk: 'multiple',
      minimizer: [
        new TerserPlugin({
          parallel: true,
          terserOptions: {
            ecma: 2015
          }
        })
      ],
      splitChunks: {
        chunks: 'all',
        maxSize: 2000000
      }
    },
    devServer: {
      contentBase: outDir,
      // serve index.html for all 404 (required for push-state)
      historyApiFallback: true,
      hot: true,
      port: 8080,
      host: 'localhost',
      proxy: {
        '/api/**': {
          target: 'http://localhost:33445/',
          secure: false,
          changeOrigin: true
        },
        '/signin-oidc': {
          target: 'http://localhost:33445/',
          secure: false,
          changeOrigin: true
        },
        '/Account/Forbidden': {
          target: 'http://localhost:33445/',
          secure: false,
          changeOrigin: true
        }
      }
    },
    devtool: prod ? undefined : 'inline-cheap-source-map',
    module: {
      rules: [
        // CSS required in JS/TS files should use the style-loader that auto-injects it into the website
        // only when the issuer is a .js/.ts file, so the loaders are not applied inside html templates
        {
          test: /\.css$/i,
          use: [MiniCssExtractPlugin.loader, 'css-loader']
        },
        {
          test: /\.less$/i,
          use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
        },
        {
          test: /\.html$/i,
          use: ['aurelia-extract-clean-loader', 'html-loader']
        },
        { test: /\.ts$/, loader: 'ts-loader' },
        // embed small images and fonts as Data Urls and larger ones as files:
        {
          test: /\.(png|gif|woff|woff2|eot|[ot]tf|svg)$/,
          loader: 'url-loader',
          options: { limit: 8192, name: 'images/[name].[ext][query]' }
        },
        {
          test: /.json$/i,
          use: { loader: 'json-loader' },
          type: 'javascript/auto'
        },
        {
          test: /environment\.json$/i,
          use: [
            {
              loader: 'app-settings-loader',
              options: { env: prod ? 'production' : 'development' }
            }
          ]
        },
        ...when(tests, {
          test: /\.[jt]s$/i,
          loader: 'istanbul-instrumenter-loader',
          include: srcDir,
          exclude: [/\.(spec|test)\.[jt]s$/i],
          enforce: 'post',
          options: { esModules: true, compact: false, produceSourceMap: true, preserveComments: true }
        })
      ]
    },
    plugins: [
      new webpack.DefinePlugin({ isDebug: JSON.stringify(!prod) }),
      new webpack.DefinePlugin({ isLocal: JSON.stringify(devServer) }),
      // ...when(!tests, new DuplicatePackageCheckerPlugin()),
      new AureliaPlugin(),
      new ModuleDependenciesPlugin({
        'aurelia-i18n': [{ name: 'locales/en/translation.json', chunk: 'en' }],
        'aurelia-testing': ['./compile-spy', './view-spy']
      }),
      new HtmlWebpackPlugin({
        template: 'index.ejs',
        filename: 'index.html'
      }),
      new MiniCssExtractPlugin({
        // updated to match the naming conventions for the js files
        filename: 'css/[name].[contenthash].bundle.css',
        chunkFilename: 'css/[name].[contenthash].chunk.css'
      }),
      ...when(analyze, new BundleAnalyzerPlugin()),
      new CleanWebpackPlugin(),
      new webpack.ProgressPlugin()
    ]
  };
};
bigopon commented 3 years ago

@PodgeHeavin the first thing that came to my mind is duplicate module. Is there any chance that you have more than 1 of aurelia core modules? An easy, though manual, way to do it is to browse the node_modules folder, though all the aurelia core modules and see if there's an internal node_modules inside them

PodgeHeavin commented 3 years ago

That seems to have been the issue. My own fault for how I imported my local version of aurelia-webpack-plugin. Thank you for your help.