Search code examples
webpackecmascript-6babel-loaderhtml-webpack-plugines6-module-loader

Webpack 4.36.1 not working with html-webpack-externals-plugin


I am migrating a library from webpack 1 to webpack 4. Which is to be consumed by another application with webpack 3.

My libraries index.js looks like this,

import * as config from './config';
export default class Helper{
    constructor(options) {
       this.configurePaths({assetPath: options.assetPath || ''});
    }
    configurePaths(configuration) {
        config.assetPath = configuration.assetPath || config.assetPath;
    }
    ...
}

Webpack of the library has:

const path = require('path');
const env = require('yargs').argv.mode;
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const JavaScriptObfuscator = require('webpack-obfuscator');
const webpack = require('webpack');

const version = require('./releaseConfig').version;
const libraryName = 'vektor3d';

let optimization = {}
let plugins = [
  new webpack.ProvidePlugin({
    vektor3d: 'vektor3d'
  })
]
let outputFile;

if (env === 'produciton') {
  optimization.minimizer =  [new UglifyJsPlugin()]
  outputFile = libraryName + '-' + version + '.min.js';
  plugins.push(new JavaScriptObfuscator({
    rotateUnicodeArray: true,
    disableConsoleOutput: false
  }, []));
} else {
  outputFile = libraryName + '.js';
}

module.exports = {
  devtool: env === 'development' ? 'source-map' : undefined,
  entry: __dirname + '/src/index.js',
  output: {
    path: __dirname+'/lib',
    filename: outputFile,
    library: libraryName,
    libraryTarget: 'umd',
    umdNamedDefine: true,
    globalObject: `(typeof self !== 'undefined' ? self : this)`
  },
  resolve: {
    modules: [path.resolve('./src')],
    extensions: ['.js']
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
            loader: 'babel-loader'
        }
      }
    ]
  },
  optimization: optimization,
  plugins: plugins
};

Now I have to include it as global in another repo whose webpack has html-webpack-plugin and looks like this:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
module.exports = {
  entry: {
    app: './src/index.js',
  },
  output: {
    filename: '[name].[chunkhash].js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/'
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: '*****'
    }),
    new HtmlWebpackExternalsPlugin({
      externals: [{
         module: 'helper',
         entry: './helper.js',
         global: 'helper',
      }]
    }),
  ],
  ...
};

And then you use it in the application as global like this:

/* global helper */
this.helper = new helper({
  assetPath: this.assetPath + '/assets/',
});

With webpack 1 helper used to be a function but with webpack 4 now its a esmodule. So new fails saying not a constructor.

I tried,

var helper = require('helper').default;

as suggested by SO answer by Felix King

edit: This part was solved in a better way with libraryExport: 'default'. But the error mentioned below persists.

But then its starts failing inside the library when using config

key: "configurePaths",
value: function configurePaths(configuration) {
  _config__WEBPACK_IMPORTED_MODULE_0__["assetPath"] = configuration.assetPath || _config__WEBPACK_IMPORTED_MODULE_0__["assetPath"];

Error:

Cannot set property assetpath of # which has only a getter

Amzingly the same command runs fine when I execute it on console after stopping it on the same line.

What am I missing? I have updated html-webpack-plugin as well to ^3.

Why does my config exposed in a way that it has only getters?


Solution

  • I was able to solve this. The problem was not with the webpack config but the way the config had been imported in the helper file. It requires export default or anouther module binder so I had to add it. This is what changed in my config file.

    config.js

    --

    export let assetPath = 'assets3d';
    

    ++

    export default {
        assetPath: 'assets3d'
     }
    

    helper.js

    --

    import * as config from './config';
    

    ++

    import config from './config';