Giter Club home page Giter Club logo

dojo-webpack-plugin's Introduction

builds coverage licenses Apache 2.0 License npm

Dojo webpack

dojo-webpack-plugin

Build Dojo 1.x applications with webpack

Introduction

dojo-webpack-plugin is a Webpack plugin that supports using Webpack to build Dojo 1.x applications that use Asyncronous Module Definition (AMD). This version supports Webpack 5 and Dojo versions 1.10 and greater (see the v2x branch for Webpack 4 support). Features include:

  • Support for Dojo loader config properties, including baseUrl, paths, packages, map and aliases
  • Support for client-side synchronous and asynchronous require() calls for packed modules.
  • Webpack loader implementations of standard Dojo loaders (e.g. dojo/text, dojo/has, dojo/i18n).
  • Limited support for client side execution of some Dojo loader extensions.

The Dojo loader

dojo-webpack-plugin uses the Dojo loader (dojo.js) at build time to resolve modules based on the properties specified in the Dojo loader config. In addition, a stripped-down build of the loader (~1.5KB after minifying and gzip) and optionally the loader config, are embedded in the packed application to support client-side execution of require() calls that have not been transformed by Webpack at build time (i.e. require() calls that reference non-stactic variables), as well as Dojo's require.toAbsMid() and require.toUrl() functions.

This package does not include the Dojo loader. A custom build of the Dojo loader is built by Webpack based on the location of Dojo specified in the Dojo loader config. Alternatively, the location of a previously built loader may be specified using the loader option. See Building the Dojo loader.

CommonJS require vs. Dojo synchronous require

Dojo supports a form of require (known as synchronous require) that has the same signature as CommonJS require. In Dojo, synchronous require returns a reference to an already loaded module, or else throws an exception if the module has not already been loaded and initialized. With this plugin, require calls matching the CommonJS/synchronous require signature which appear followng the first define call in an AMD modules are treated as Dojo synchronous require calls. If you wish to load a CommonJS module from within an AMD module, you may do so by calling require before the first define call, or else by using the cjsRequire function that is supported by the plugin.

var lodash = require("lodash");			// CommonJS require
define([], function() {
	var query = require("dojo/query");	// Dojo synchronous require
	var async = cjsRequire("async");	// CommonJS require
});

If CommonJS require calls are being injected into your module by third-party code (e.g. by ProvidePlugin), then you can use the cjsRequirePatterns option to specify regular expression patterns to match against module names that should be loaded using CommonJS require.

The Dojo loader config

The loader config defines properties used in resolving module identifiers as described in Configuring Dojo with dojoConfig. Note that not all properties in the loader config are used by Webpack. Only properties relating to module name/path resolution are used. These include baseUrl, packages, paths, map and aliases. The loader config may also specify a has map of feature-name/value pairs. The has features are used in resolving dojo/has loader conditionals at build time, and to provide the initial values for the run-time has.js feature detection functionality provided by dojo/has. The loader config is specified by the loaderConfig options property:

const DojoWebpackPlugin = require('dojo-webpack-plugin');
//...
plugins: [
	new DojoWebpackPlugin({
		loaderConfig: require("./loaderConfig"),
		locales: ["en", "es", "fr"]
	})
	//...
]

The loader config may be specified as an object, a function that returns the config object, or as a string which represents the name of a CommonJS module that exports the config (object or function). If specified as an object or a function, then the config expressions are evaluated at build time and the config object is serialized to the client and mixed with the window.dojoConfig property at application load time.

If the config is specified as a module name, then the config module will be evaluated both at build time (for the purpose of resolving modules for webpack), and then again at application run time when the config module is loaded on the client. Note that if you want webpack to process the config module (i.e. perform build time variable substitution, etc.) then you must specify the config as a module name.

If you want the config to specify different properties at build time vs. run time, then specify the config as a function that returns the config object and use the environment and buildEnvironment options to set the properties who's values change depending on the target environment. This works both when the config is evaluated at build time (specified as a function) and when the config is evaluated at build time and runtime (specified as the name of a CommonJS module that exports a function).

This plugin does not support the dojoConfig deps and callback properties. The same functionality can be provided by requiring your dependencies in the webpack entry module. For example:

// entry.js
require(/* dojoConfig.deps */ ['dep1', 'dep2'], function(dep1, dep2) {
	// dojoConfig.callback code here
});

See js/loaderConfig.js in the sample project for an example of a Dojo loader config that uses the environment and buildEnvironment options to specify different config paths for build time vs run time. The config also supports running the sample app as a non-packed application with Dojo loaded from a CDN.

Dojo loader extensions

Loader extensions are used to provide special processing when loading modules. Loader extensions prefix the module being loaded, separated by the ! character. Both Dojo and Webpack have the concept of loader extensions and use similar syntax, but the implementation are very different, and they use conflicting terminology. Dojo refers to them as plugins and Webpack refers to them as loaders. To avoid confusion, we refer to them both in this document as loader extensions.

Dojo loader extensions generally cannot be used with Webpack. There are several config only approaches to dealing with Dojo loader extensions that don't require changing your application's code.

  • Use the NormalModuleReplacementPlugin to replace the Dojo loader extension with a compatible Webpack loader extension. For example, the dojo/text loader extension can be replaced with the Webpack raw loader extension. This can be done with code similar to the following in your webpack.config.js.

     const DojoWebpackPlugin = require('dojo-webpack-plugin');
     //...
     plugins: [
     	new DojoWebpackPlugin({/*...*/}),
     	new webpack.NormalModuleReplacementPlugin(/^dojo\/text!/, function(data) {
     		data.request = data.request.replace(/^dojo\/text!/, "!!raw-loader!");
     	}),
     	//...
     ]

    This replacement (among others) is automatically configured for you, so you don't need to include this in your webpack.config.js. It is provided here as an example of what you could do with other loader extensions.

  • Use the NormalModuleReplacementPlugin to replace the entire module expression with the desired module. Some Dojo loader extensions are used to dynamically load one module or another based on runtime conditions. An example is the gfx loader, which loads the rendering engine supported by the client. Since all modern browsers support the canvas rendering engine, you can replace the module expression that includes the loader with the module expression for the target module.

     new NormalModuleReplacementPlugin(/^dojox\/gfx\/renderer!/, "dojox/gfx/canvas")
  • Implement the Dojo loader extension as a Webpack loader extension. This is what has been done with the dojo/text and dojo/i18n loader extensions.

  • Use the NormalModuleReplacementPlugin with the dojo/loaderProxy loader extension provided by this package to proxy Dojo loader extensions on the client. More information on this is provided in The dojo/loaderProxy loader extension.

dojo-webpack-plugin defines the following loader extension replacements:

new webpack.NormalModuleReplacementPlugin(/^dojo\/selector\/_loader!default$/, "dojo/selector/lite"),
new webpack.NormalModuleReplacementPlugin(/^dojo\/request\/default!$/, "dojo/request/xhr"),
new webpack.NormalModuleReplacementPlugin(/^dojo\/query!/, data => {
		var match = /^dojo\/query!(.*)$/.exec(data.request);
		data.request = "dojo/loaderProxy?loader=dojo/query&name=" + match[1] + "&absMid=dojo/query%21" + match[1] + "!";
})

The dojo/has loader extension

Dojo supports conditionally depending on modules using the dojo/has loader extension. dojo-webpack-plugin supports both build-time and run-time resolution of dojo/has loader expressions. Consider the following example:

define(['dojo/has!foo?js/foo:js/bar'], function(foobar) {
	//...
});

In the above example, if the feature foo is truthy in the static has features that are defined in the dojo loader config, then the expression will be replaced with the module name js/foo at build time. If foo is falsy, but not undefined, then it will be replaced with the module name js/bar. If, on the other hand, the feature foo is not defined, then resolution of the expression will be deferred to when the application is loaded in the browser and the run-time value of the feature foo will be used to determine which module reference is provided. Note that for client-side resolution, both resources, js/foo and js/bar, along with their nested dependencies, will be included in the packed assets.

For complex feature expressions that contain a mixture of defined and undefined feature names at build time, the runtime expression will be simplified so that it contains only the undefined feature names, and only the modules needed for resolution of the simplified expression on the client will be included in the packed resources. Modules that are excluded by build time evaluation of the expression with the static has features will not be include in the packed resources, unless they are otherwise include by other dependencies.

This plugin defines the webpack feature with a value of true if it is not already defined by the app.

The coerceUndefinedToFalse option can be used to cause undefined features to evaluate to false at build time. If this options is true, then there will be no conditional load expressions in the generated code.

The runtimeFeatures option allows you to change the values of selected, statically defined, features at runtime for testing purposes.

You may use webpack-hasjs-plugin if you want to perform has.js filtering of source code at build time using statically defined features.

moduleIds

By default, webpack uses the resource path of the module as the module id in development builds. In production builds, integer modules ids are used. Using named module ids helps with debugging, but can trip up the parsing of dojo/has loader expressions when the module ids contains ? and : characters. For this reason, it is recommended to disable the use of named module ids with the following option in your webpack config:

optimization: {
	moduleIds: 'natrual'
}

The dojo/loaderProxy loader extension

dojo/loaderProxy is a Webpack loader extension that enables Dojo loader extensions to run on the client. If the dojo loader is asynchronous (i.e. does not invoke its load callback in-line), then you must specify the async option. The most common use cases are loader extensions that delegate to dojo/text or another supported loader extension to load the resource before doing some processing on the result.

Consider a simple svg loader extension that loads the specified svg file and fixes up the contents by removing the xml header in the content. The implementation of the load method might look like this:

function load(name, req, callback) {
	req(["dojo/text!" + name], function(text) {
		callback(stripHeader(text).trim());
	});
}

Here, the load method delegates to a loader extension that is supported by Webpack to load the resource. If the resource is included in the packed modules, then the req callback will be invoked in-line, and thus the load method's callback will be invoke in-line. If the load method's callback is not invoked before the load method returns, then an exception will be thrown if the async option is not used.

You can use dojo/loaderProxy with the Webpack NormalModuleReplacementPlugin as follows:

new webpack.NormalModuleReplacementPlugin(
	/^svg!/, function(data) {
		var match = /^svg!(.*)$/.exec(data.request);
		data.request = "dojo/loaderProxy?loader=svg&deps=dojo/text%21" + match[1] + "!" + match[1];
	}
)

The general syntax for the dojo/loaderProxy loader extension is dojo/loaderProxy?loader=<loader>&deps=<dependencies>&name=<resource>!<resource> where loader specifies the Dojo loader extension to run on the client and dependencies specifies a comma separated list of module dependencies to add to the packed resources. In the example above, if the client code specifies the module as svg!closeBtn.svg, then the translated module will be dojo/loaderProxy?loader=svg&deps=dojo/text%21closeBtn.svg!closeBtn.svg. Note the need to URL encode the ! character so as not to trip up parsing.

Specifying dojo/text!closeBtn.svg as a dependency ensures that when it is required by the svg loader extension's load method on the client, then the dependency will be resolved in-line and the load method's callback will be invoked in-line as required.

The name query arg is optional and is provided for cases where the resource name (the text to the right of the "!") does not represent the name of a module that can be resolved at build time. Since webpack requires the resource name to represent a valid module, you can use the name query arg to specify non-module resources or resources that are not available at build time (see notes on the async option below). For example, the loaderProxy URL for dojo/query!css2 would be dojo/loaderProxy?loader=dojo/query&name=css2!.

Options

The plugin is instantiated with a properties map specifying the following options:

async

This property specifies that AMD modules should be defined asynchronously.

Using async mode allows the dojo/loaderProxy plugin to support Dojo loader extensions that resolve asynchronously.

One major caveat to using async mode is that if CommonJS require is used to load an AMD module, the returned value can be an un-resolved promise. For this reason, you should always load AMD modules asynchronously from CommonJS modules unless you can be certain that the module is already defined. For example:

// From within a CommonJS module
Promise.resolve(require('myAmdModule')).then(function(myAmdModule) {
	myAmdModule.doSomething();
});

Because async mode depends on ES6 Promise, you need to provide a polyfill on platforms that don't support Promise natively (e.g. IE11). You can use the Dojo ES6 Promise polyfill for this purpose.

Wrapped promises

This section is for the special (and hopefully rare) case of requiring, from CommonJS code, an AMD module that itself returns a promise as the module value. It applies only when the async option is true. If you're not doing this in your code, then you can ignore this section.

dojo-webpack-plugin wraps module value promises (actually, any thenable) in a non-promise object. This is done in order to prevent promise chaining from replacing the promise with the resolved value before it is provided to the caller. Promise wrapping and unwrapping happens transparently within AMD modules, so you don't need to be concerned with it. When an AMD module is required from CommonJS code, however, then the promise wrapper can be exposed and you need to take steps to deal with it, as shown in the following example:

// From within a CommonJS module
const unwrap = require('dojo-webpack-plugin/cjs/unwrapPromiseValue');

Promise.resolve(require("amdModuleThatHasPromiseValue"))
  .then(wrapped => unwrap(wrapped))
  .then(resolved => {
		resolved.doSomething();
	});

Note that it is safe to call unwrap for non-wrapped modules, and to call it with the value returned by previous calls to unwrap. If the input module is not a wrapped promise, then the input value is returned.

loaderConfig

This property is required and specifies the Dojo loader config. See The Dojo loader config for details.

environment

If the loader config evaluates to a function, then this property specifies the object that is passed to the function when it is called to get the config object. This should be a JSON type object because it may get stringified for export to the client.

buildEnvironment

Simialr to environment, but used exclusively at build time. If both are specified, then buildEnvironment will be passed to the loaderConfig function when building, and environment will be passed to the loaderConfig function when the config is evaluated for use in the browser. This facilitates specifying different loaderConfig paths (e.g. baseUrl) for build vs. run. If only environment is specified, then it is used for both.

globalContext

Specifies the path to use for resolving relative module ids passed to the global require function. Dojo resolves these against the page URL. If this option is specified as a relative path, then it is resolved against the webpack compiler context. If not specified, it defaults to the webpack compiler context.

Note that the globalContext option is different than the Dojo loader config's baseUrl property in that it is used only for resolving relative path module identifiers (those that begin with a .) passed to the global require function. In contrast, the baseUrl property is used for resolving non-relative module ids that don't map to a defined package or path.

loader

This property is optional and specifies the module path of the built Dojo loader. See Building the Dojo loader for details. If not specified, then the loader will be built as part of the Webpack build.

locales

This property optional and specifies which locale resources should be included in the build. The property is specified as an array of strings. If not specified, then all available locales resources will be included. If specified as an empty array, then only the default (root) locale resources will be included.

cjsRequirePatterns

This property is optional and specifies an array of regular expressions to use in identifying CommonJS module identifiers within AMD modules.

See CommonJS require vs. Dojo synchronous require. Some Webpack plugins (e.g. ProvidePlugin) can inject CommonJS calls directly into your AMD modules. This property provides a mechanism for those modules to be loaded as CommonJS modules. If any of the regular expressions specified match the module identifier in a candidate require call (within an AMD module), then the module will be loaded as a CommonJS module. If none of the patterns match, then the require call will be processed as a Dojo synchronous require call.

If not specified, the default pattern (imports-loader|exports-loader)[?!] is used. This pattern will match many of the common use cases for the ProvidePlugin. Note that if you specify this property, the values you specify replace the default value.

coerceUndefinedToFalse

This property is optional. If the value is truthy, then undefined features will be treated as false for the purpose of dojo/has loader plugin feature evaluation at build time. See The dojo/has loader extension for more information.

noConsole

This property is optional. If the value is truthy, then console output from building the Dojo loader will be suppressed.

runtimeFeatures

This property is optional. If specified, it is an array of strings which specifies the names of features (has! loader conditionals) that are to be evaluated at run time rather than at build time, even if the feature is assigned a value at build time.

You would typically want to specify this option when running unit tests and your tests use require.undef() to undefine modules and then load them again using require() with different values for the features. Normally, if a feature is given a value at build time (e.g. in the loader config), then the has! loader conditional is fixed and cannot be changed at run time. With this option, the initial values of the specified features will be those assigned by the build, but you'll be able to change the values of these features and the has! loader conditionals in the dependency array of the module that's being loaded or reloaded will work as expected.

ignoreNonModuleResources

This optional property is a boolean value (default = false) which specifies that the plugin should not attempt to resolve non-module resources. By default, this plugin attempts to resolve both module and non-module resources using the Dojo loader config. Any resources not resolved using the Dojo loader config are resolved using the Webpack config. An example of non-module resources that may be resolved in this way is less/css imports where the url is preceded by a tilde.

@import '~myStylesPakage/styles.css';

The tilde tells Webpack to resolve the import 'like a module'. If you do not want dojo-webpack-plugin to resolve non-module resources and instead let let Webpack resolve them using the Webpack config, then set this option to true.

Building the Dojo loader

This plugin embeds a custom build of the Dojo loader (dojo.js) in your packed application. The built loader is packaged as a CommonJS module so that it may be more easily consumed by Webpack. The loader build profile specifies has.js features which exclude unneeded code (e.g. for loading modules) so that the loader embedded into the client is as small as possible (~1.5KB after uglify and gzip)[1]. The Dojo loader builder requires that the Dojo util directory is a sibling of the dojo directory and is named either util or dojo-util.

If you do not want to build the Dojo loader every time Webpack is run, then you can build it manually and specify the location of the built loader using the loader option. You can produce a manual build of the loader by running the build script in the buildDojo directory.

    node node_modules/dojo-webpack-plugin/buildDojo/build.js node_modules/dojo/dojo.js ./release

You can also build the loader from a Node script as shown below.

const buildLoader = require('dojo-webpack-loader').buildLoader;
buildLoader({
	dojoPath: "node_modules/dojo/dojo.js",
	releaseDir: "./release"
}).then(() => {
  console.log("loader built");
}).catch(err => {
  console.error(err);
});

The examples above will build the loader and place it in the ./release directory, relative to the current directory.

To have Webpack use the built loader, specify the location of the loader in the plugin options as follows:

plugins: [
	new require("dojo-webpack-plugin")({
		loaderConfig: require("./loaderConfig"),
		locales: ["en"],
		loader: path.join(__dirname, "./release/dojo/dojo.js")
	}),
]

Overriding profile features

By default, the embedded loader is built using the static features defined here. You may override these features by providing an optional, third argument to the build script which specifies the features you want to override as a JSON string. For example, if you specify the loaderConfig option as an object, or a function that returns an object (as opposed to specifying it as a module name), then you can make the embedded loader smaller by omitting the config api. See The dojo-config-api feature. This would be done as follows:

  node node_modules/dojo-webpack-plugin/buildDojo/build.js node_modules/dojo/dojo.js ./release {\"dojo-config-api\":false}

Or, if calling the buildLoader function in Node, specify the has property as an object map of feature name/value pairs.

The dojo-config-api feature

A modest reduction in the size of the bootstrap code can be realized by excluding the code needed for loading and parsing the Dojo loader config from the embedded Dojo loader. This can only be done if the loaderConfig option is specified as an object or function. It cannot be done if the loaderConfig option is specified as a module name because of the need for the embedded Dojo loader to process the loader config on the client.

When using an embedded Dojo loader that does not include the config API, post-processed config objects generated at build time are serialized to the application and used to initialize the embedded loader at application run-time. The pre-processed config objects (e.g. paths, packages, aliases, maps, etc.) are not serialized to the application because they are not needed by Dojo. If your application uses window.dojoConfig to initialize Dojo properties at application load-time or requires access to window.dojoConfig or require.rawConfig, then don't use this feature.

This plugin detects at application build time whether or not the embedded Dojo loader includes the config API and emits the code for initializing the application as appropriate for the type of loader provided.

There are two ways to use the embedded Dojo loader without the config API.

  1. If the plugin is building the loader automatically at application build time (i.e. you are not specifying the loader option), then you can specify the dojo-config-api feature with a value of 0 or false in the Dojo loader config has property. Note that the dojo-config-api has feature is ignored if the loaderConfig option specifies a module name.

    plugins: [
    	new DojoWebpackPlugin({
    		loaderConfig: {
    			paths: {/*...*/},
    			packages: [/*...*/],
    			has: {'dojo-config-api':false}
    		}
    		// ...
    	})
    ]
  2. If you are specifying a pre-built embedded loader using the loader option, then build the loader without the config API as described in Overriding profile features. Note that a build-time exception will be thrown if the loaderConfig option specifies a module name and the provided loader does not include the config API.

The dojo-undef-api feature

This plugin supports the dojo-undef-api feature. If this feature is enabled in the Dojo loader config's has property at build time, then require.undef may be called at runtime to remove a module from the list of defined modules. This generally works only with AMD modules, not CommonJS modules. require.undef is primarily useful for test frameworks that need to load and unload modules without having to reload the entire application.

ES6 Promise polyfill

Webpack 2.x and greater includes code in your packed application that uses ES6 Promise. If you need to support browsers that lack ES6 Promise support (e.g. IE 11), then you will need to provide this capability in your application. This plugin provides a tiny wrapper module named dojoES6Promise that implements ES6 Promise using dojo/Deferred. All you need to do is include this module as an AMD dependency in your application. See bootstrap.js in the sample application for an example.

Order of Plugin Registration

When using Webpack's NormalModuleReplacementPlugin, the order of the plugin registration relative to the dojo-webpack-plugin registration is significant. dojo-webpack-plugin converts the module expressions to an absMid (relative paths resolved, maps and aliases applied), so if the NormalModuleReplacementPlugin is registered after dojo-webpack-plugin, then data.request will contain the absMid for the module and data.originalRequest will contain the original module expression before transformation by dojo-webpack-plugin. If the NormalModuleReplacementPlugin is registered before dojo-webpack-plugin then the NormalModuleReplacementPlugin will get to modify the request before dojo-webpack-plugin applies its transformations.

The global require function

Like Dojo, this plugin differentiates between the global require function and context-sensitive require. This distinction affects how module identifiers with relative paths are resolved. When using context-sensitive require, relative paths are resolved against the path of the containing module. When using global require, Dojo resolves relative paths against the page URL, while this plugin resolves them against the path specified by the globalContext option, or the webpack compiler context path.

Also like Dojo, this plugin defines window.require in global scope on the client. The global require function implements Dojo's synchronous require capability. This works great for Dojo applications but it can be a problem in some scenarios involving other (non-webpack) loaders or frameworks. For those situations where it is not desirable to overwrite window.require, you can use the ScopedRequirePlugin plugin. The ScopedRequirePlugin plugin leaves window.require untouched, and instead defines require in a scope that encloses each AMD module. Note that this scoped require is similar to the global require in that it is not associated with any module's context and cannot be used to load modules with paths relative to the calling module. For that you need to use a context-sensitive require defined within your module.

To use the ScopedRequirePlugin plugin, register the plugin after dojo-webpack-plugin in your webpack.config.js file.

const DojoWebpackPlugin = require('dojo-webpack-plugin');
  // ...
  plugins: [
    new DojoWebpackPlugin({
      loaderConfig: {/*...*/},
      locales: [/*...*/]
    }),
    new DojoWebpackPlugin.ScopedRequirePlugin()
  ]

Use of run-time identifiers and expressions in dependency arrays

The plugin supports the use of run-time identifiers and expressions in require/define dependency arrays with the caveat that the modules referenced by the identifiers or expressions must be available in chunks that have already been loaded on the client. For example:

var fooName = 'foo';
function getBarName() {
	return 'bar';
}
require([fooName, getBarName(), 'baz'], function(foo, bar, baz) {
	/* ... */
});

In order for the above code to execute successfully, the modules foo and bar must be available on the client when the callback is invoked, otherwise, an exception will be thrown. This means that the modules must have been included in a previously loaded chunk, or they must be direct or indirect dependencies of baz so that they are included in the chunk(s) being loaded. Since values of run-time identifiers or expressions, in general, cannot be known at build time, webpack cannot manage the loading of these modules or their dependencies.

Note that you can also specify the require dependency array as a run-time identifier, with the same restrictions applying to all the modules in the array.

Use of Dojo's Auto-Require feature

Dojo's Auto-Require feature allows the parser to automatically require the modules for widgets that are declared by templates. This can be problematic with webpack for the reasons discussed above, if your modules do not explicitly specify dependencies for the widgets that they contain. Although useful for prototyping and demo purposes, Dojo itself recommends against using Auto-Require for production code because of it's negative performance consequences, and to instead be explicit about your application's dependencies.

Dependency requirements

dojo-webpack-plugin has a peer dependency on webpack. dojo-webpack-plugin's webpack dependencies must resolve to the same modules as your application's webpack dependencies, otherwise you may encounter errors similar to the following when building.

Error: Cannot find module 'webpack-core/lib/ConcatSource'

The best way to ensure that the requirement is met is to make sure that both this plugin and webpack are installed in the same node_modules directory, and to use flat, rather than hierarchical, tree dependency resolution (the default for npm v3 and above) when using npm to install the packages.

Sample application

See the sample application at https://github.com/OpenNTF/dojo-webpack-plugin-sample.

https://openntf.github.io/dojo-webpack-plugin-sample/test.html.

dojo-webpack-plugin's People

Contributors

chuckdumont avatar dependabot[bot] avatar dpwatrous avatar g3r4n avatar gordonsmith avatar grigorii-zander avatar heikostudt avatar maier49 avatar vog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dojo-webpack-plugin's Issues

Object.defineProperties error when using webpack-dev-server

I'm using webpack-dev-server 2.11.1 and webpack 3.11.0.

With version 2.6.0 of the dojo-webpack-plugin, I can build fine with webpack, but if I use webpack-dev-server, I get the following error.

TypeError: Cannot redefine property: compilation
    at Function.defineProperties (<anonymous>)
    at Compiler.compiler.plugin (/Users/rene8209/Sites/demos/arcgis-webpack-plugin-sample/node_modules/dojo-webpack-plugin/lib/DojoAMDModuleFactoryPlugin.js:49:12)

Looks like this recent change here is causing some issue with dev-server.
https://github.com/OpenNTF/dojo-webpack-plugin/blob/master/lib/DojoAMDModuleFactoryPlugin.js#L49-L52

  Object.defineProperties(context, {
    compilation: {value: compilation},
    params: {value: params}
  });

Module not found (script tag)

Hello,

I have an error when using script tag inside a webpage:

image

package.json:

"dependencies": {
  },
  "devDependencies": {
    "@babel/core": "^7.4.5",
    "@babel/preset-env": "^7.4.5",
    "babel-loader": "^8.0.6",
    "copy-webpack-plugin": "^5.0.3",
    "css-loader": "^3.0.0",
    "dgrid": "^1.2.1",
    "dijit": "^1.15.0",
    "dojo": "^1.15.0",
    "dojo-themes": "^1.14.1",
    "dojo-util": "^1.15.0",
    "dojo-webpack-plugin": "^2.8.9",
    "dojox": "^1.15.0",
    "less": "^3.9.0",
    "less-loader": "^5.0.0",
    "style-loader": "^0.23.1",
    "uglifyjs-webpack-plugin": "^2.1.3",
    "url-loader": "^2.0.1",
    "webpack": "^4.35.2",
    "webpack-cli": "^3.3.5",
    "webpack-watch-files-plugin": "^1.0.3"
  },
  "scripts": {
    "build": "webpack",
    "build:dev": "webpack --env.dev",
    "serve": "webpack-dev-server --env.dev",
    "dev": "webpack --watch"
  },

Webpack:
entry: js/start.js

js/start.js:

require([
    "My/App",
    "theme/app/backend.less"
]);

require(["dojo/parser", "dojo/ready", "dijit/layout/TabContainer", "dojo/dom-style", "dojo/query", "dojo/store/JsonRest", "dijit/form/ComboBox", "dijit/form/Select"], function (parser, ready) {
    ready(function () {
        parser.parse();
    });
});

Page (before </body>):

<script type="text/javascript">
    require(["dojo/dom-style", "dojo/query", "dojo/ready"], function (domStyle, query, ready) {
        ready(function () {
            ...
        });
    });
</script>

Module not found: Can't resolve 'dojo/has' in ..... - Error with webpack build

Hi,

I am trying to use the dojo-webpack-plugin with webpack and am seeing a build error related to 'dojo/has' module:

Module not found: Can't resolve 'dojo/has' in .....

Here is the entryPoint to my application

require([
  'DemoJSES6-ui/js/start',
  'dojo/domReady!',
  'dojo/has!dom-addeventlistener?:dojo/aspect'
], async (startPromise) => {
  startModule = await startPromise;
  startModule.start();
});

My webpack.config.js has the following configuration for dojo-webpack-plugin:

plugins: [
            new DojoWebpackPlugin({
                loaderConfig: require(path.resolve(sbroot, "/loaderConfig")),
                environment: {dojoRoot: "./release"},
                buildEnvironment: {dojoRoot: sbroot}, 
                async: true
    }),

and, my loaderConfig is aware of the location of the dojo module:

packages: [
                name: 'dojo',
	        location: env.dojoRoot + '/ui/dojo',
		lib: '.'
		},

Can you please help understand the cause of the problem here?

Thanks,
Tushar

Duplicate absMid

I get 'Duplicate absMid' on 2.8.5 version:

ERROR in chunk calendar [entry]
Duplicate absMid ("lib/core") for modules "C:\\P\\git\\c8\\Projects\\WebAccess\\node_modules\\diagram-js\\lib\\core\\index.js" and "C:\\P\\git\\c8\\Projects\\WebAccess\\node_modules\\bpmn-js\\lib\\core\\index.js"
Error: Duplicate absMid ("lib/core") for modules "C:\\P\\git\\c8\\Projects\\WebAccess\\node_modules\\diagram-js\\lib\\core\\index.js" and "C:\\P\\git\\c8\\Projects\\WebAccess\\node_modules\\bpmn-js\\lib\\core\\index.js"
    at DojoAMDChunkTemplatePlugin.<anonymous> (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDChunkTemplatePlugin.js:77:11)
    at module.filterAbsMids.module.filterAbsMids.absMid (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDChunkTemplatePlugin.js:83:5)
    at absMids.forEach.absMid (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDModuleFactoryPlugin.js:232:8)
    at Array.forEach (<anonymous>)
    at DojoAMDModuleFactoryPlugin.filterAbsMids (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDModuleFactoryPlugin.js:231:11)
    at SyncHook.eval [as call] (eval at create (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:7:1)
    at callHook (C:\P\git\c8\Projects\WebAccess\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:130:21)
    at callSync (C:\P\git\c8\Projects\WebAccess\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:137:10)
    at NormalModule.module.filterAbsMids.callback [as filterAbsMids] (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDModuleFactoryPlugin.js:409:4)
    at modules.forEach (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDChunkTemplatePlugin.js:82:35)
    at Array.forEach (<anonymous>)
    at DojoAMDChunkTemplatePlugin.renderAbsMids (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDChunkTemplatePlugin.js:80:11)
    at SyncWaterfallHook.eval [as call] (eval at create (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:7:16)
    at SyncWaterfallHook.lazyCompileHook (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\Hook.js:154:20)
    at callHook (C:\P\git\c8\Projects\WebAccess\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:130:21)
    at callSyncWaterfall (C:\P\git\c8\Projects\WebAccess\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:140:10)
    at DojoAMDMainTemplatePlugin.dojoRequireExtensions (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDMainTemplatePlugin.js:99:12)
    at SyncWaterfallHook.eval [as call] (eval at create (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:7:16)
    at SyncWaterfallHook.lazyCompileHook (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\Hook.js:154:20)
    at callHook (C:\P\git\c8\Projects\WebAccess\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:130:21)
    at callSyncWaterfall (C:\P\git\c8\Projects\WebAccess\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:140:10)
    at DojoAMDMainTemplatePlugin.requireExtensions (C:\P\git\c8\Projects\WebAccess\node_modules\dojo-webpack-plugin\lib\DojoAMDMainTemplatePlugin.js:80:10)
    at SyncWaterfallHook.eval [as call] (eval at create (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:17:16)
    at SyncWaterfallHook.lazyCompileHook (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\Hook.js:154:20)
    at MainTemplate.renderBootstrap (C:\P\git\c8\Projects\WebAccess\node_modules\webpack\lib\MainTemplate.js:406:55)
    at MainTemplate.updateHashForChunk (C:\P\git\c8\Projects\WebAccess\node_modules\webpack\lib\MainTemplate.js:534:27)
    at Compilation.createHash (C:\P\git\c8\Projects\WebAccess\node_modules\webpack\lib\Compilation.js:2325:14)
    at hooks.optimizeTree.callAsync.err (C:\P\git\c8\Projects\WebAccess\node_modules\webpack\lib\Compilation.js:1288:9)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\HookCodeFactory.js:32:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\Hook.js:154:20)
    at Compilation.seal (C:\P\git\c8\Projects\WebAccess\node_modules\webpack\lib\Compilation.js:1244:27)
    at hooks.make.callAsync.err (C:\P\git\c8\Projects\WebAccess\node_modules\webpack\lib\Compiler.js:624:17)
    at _done (eval at create (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\HookCodeFactory.js:32:10), <anonymous>:9:1)
    at _err17 (eval at create (C:\P\git\c8\Projects\WebAccess\node_modules\tapable\lib\HookCodeFactory.js:32:10), <anonymous>:224:22)
    at _addModuleChain (C:\P\git\c8\Projects\WebAccess\node_modules\webpack\lib\Compilation.js:1095:12)
    at processModuleDependencies.err (C:\P\git\c8\Projects\WebAccess\node_modules\webpack\lib\Compilation.js:1007:9)

Webpack - 4.29.6

Support for `require` with config parameter

Hi Chuck,

In our tests we use the config parameter for the require function sometimes to load mocked modules.
E.g.

  require({ map: { '*': {
    'my/module/path': 'my/mocked/module/path'
  }}}, ['the/module/under/test', function etc(...) {...});

this is partly why we needed the undef function, to make sure the the/module/under/test is loaded freshly with the mocked modules.
Would it be feasible to implement something like this for the webpack plugin?

Thanks, Ronald

dojoConfig alias path not resolved by webpack

Hi folk,

Not sure if it's an issue or if I'm doing something wrong, but here is my problem.
I'm having module loaded that way in my app:

define([
    "dojo/_base/declare",
    "esri/Map",
    "esri/config",
    "dojo/_base/array",
    "dojo/promise/all",
    "app/Coordinates",
    "app/tasks/Print"
	], function(...)) {}

Where "app" path is an alias defined in the dojoConfig as follow:

packages: [
	{
		name: "app",
		location: base + "/js/map"
	}
]

I'm trying to get webpack to solve this path by providing the loaderConfig as mentionned in the doc, with a function and it should take into account my packages variable, or even path that I defined right?
As mentionned here https://github.com/OpenNTF/dojo-webpack-plugin#the-dojo-loader-config.

Unfortunately I get a error message telling me

Module not found: Error: Can't resolve 'app/Coordinates'

for example.

Do you have any idea how webpack handle the dojoConfig pass as an argument in the dojo-webpack-plugin and how to make this alias path resolvable.

Thanks a lot.

Update for Webpack 4

Currently the plugin doesn't work with Webpack 4. I'm trying 4.0.1.
It fails on this section
https://github.com/OpenNTF/dojo-webpack-plugin/blob/master/lib/DojoLoaderPlugin.js#L38

This is the error.

Error: Plugin could not be registered at 'get dojo require'. Hook was not found.
BREAKING CHANGE: There need to exist a hook at 'this.hooks'. To create a compatiblity layer for this hook, hook into 'this._pluginCompat'.

Looking at this issue it has breaking change for plugins.

new plugin system
plugin method is backward-compatible
Plugins should use Compiler.hooks.xxx.tap(<plugin name>, fn) now

There's a comment in there that references how a migration from 3 to 4 would look.

I've forked this project, but I was just starting to learn how to write a webpack plugin from the previous guide, so not sure how quickly I could do a PR on this update.

Thanks!

unit testing with intern

Hi Chuck,

Do you have any experience how to set up intern unit tests in combination with the dojo-webpack-plugin?

Kind regards, Ronald

Using this plugin inside ReactJs

I had a question as to whether it would be feasible to try using this loader with React. Specifically I'm looking to be able to incorporate imports of Dojo code into React eg.
import * as domStyle from 'dojo/dom-style'

I've looked at the two example projects and they seem to mostly use the normal Dojo syntax for requiring modules. Ideally I would want to be able to bundle the React and Dojo code together.

import * as domStyle from 'dojo/dom-style'

class App extends Component {
     //react code
     //call dojo module
     componentDidMount() {
          domStyle.set(/*something with the DOM here*/)
     }
}

Is there any way to specify which files(specifically the dojo modules) I would want to consume and then send along to be imported with say ES6 import syntax? Is this something this plugin could theoretically support?

Question about how to handle "define cannot be used indirect" error in loading an application built with webpack

Hi Chuck,

We have another question to which we haven't been able to find a solid answer.

We have some code that looks like the following:

var modulesToLoad = [
    "dojo/_base/declare",
    "dojo/_base/lang",
    "dijit/layout/_LayoutWidget",
    "dijit/_TemplatedMixin",
    "dijit/Destroyable",
    // other local modules
];

if (<condition> ) {
     modulesToLoad = modulesToLoad.concat([<OPTIONAL_MODULE>]);
}

define (modulesToLoad, function( .... ) {
....
)};

We are able to build this code using webpack. However, when we load the application, we receive the "define cannot be used indirect" error.

As a temporary workaround, we are simply adding the optional module to the entire array and passing that to define:

define([
    "dojo/_base/declare",
    "dojo/_base/lang",
    "dijit/layout/_LayoutWidget",
    "dijit/_TemplatedMixin",
    "dijit/Destroyable",
    "<OPTIONAL_MODULE>"
], 

We think that we're likely just missing some plugin in our webpack.config.js that will allow an array variable to be used in define. Can you confirm that? Is there something else we're missing?

Thanks!
-Chris

Support lazy loading AMD plugin modules

I have a Dojo project that uses AMD plugins that load resource dynamically. These resources are only available at runtime, not build time. At runtime, my plugin tries to load the resource asynchronously and since the loaderProxy expects the plugin to load synchronously, I get an error that indicates that the module is unavailable. To give an example of what I'm working with:

define([
    "dojo/request/script"
], function(script) {
    var cache = {};
    var pending = {};

    return {
        load: function(id, req, callback) {
            if(id in cache) {
                callback(cache[id]);
                return;
            }
            else if(id in pending) {
                // Hold onto the callback so we can resolve the call once the module loads
                pending[id].push(callback);
                return;
            }

            pending[id] = [callback];

            var path = ...; // resolve id to a resource path
            script.get(path).then(function() {
                // Once the module is loaded into global space, get a handle on the module
                var module = ...;

                // Resolve pending module requests
                var allPending = pending[id];
                for(var i = 0; i < pendingList.length; i++) {
	            allPending[i](module);
                }

                delete pending[id];
            });
        }
    };
});

There are then many other modules that depend on this plugin. For example:

define([
    "my/plugin!my-module"
], function(myModule) {
    // leverage the module directly
});

Is this something that can be supported? I'd be happy to help, just have no idea where to start given I'm new to webpack and the dojo-webpack-plugin.

Full paths to modules are being left in production output bundles

I'm working with the arcgis js api and webpack plugin which uses this plugin under the hood.

I'm running into constant issues where sometimes after running a build, I'll run into errors where the workers fail to load. It doesn't happen all of the time, and it sometimes resolves itself for no apparent reason. I realize this might not even be related to your plugin, but if you have any ideas to offer, I would love to hear them. This is sort of a last ditch effort in fixing this reoccurring issue.

Looks like this is the dojo config the esri webpack plugin uses:

These are the errors I'm getting:

1

VM53057:1 Access to XMLHttpRequest at 'file:///C:/Users/<username>/web/dl2-datafi/node_modules/arcgis-js-api/core/workers/worker.js' from origin 'http://lvh.me:9000' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

2

[esri.core.workers] Failed to create Worker. Fallback to execute module in main thread 
t {name: "request:server", message: "Unable to load C:/Users/<username>/web/dl2-datafi-…es/arcgis-js-api/core/workers/worker.js status: 0", details: {…}}
details: {url: "C:/Users/<username>/web/dl2-datafi/node_modules/arcgis-js-api/core/workers/worker.js", requestOptions: {…}, getHeader: ƒ, httpStatus: 0, subCode: undefined, …}
message: "Unable to load C:/Users/<username>/web/dl2-datafi/node_modules/arcgis-js-api/core/workers/worker.js status: 0"
name: "request:server"

image

3

Error: Module not found: C:/Users/<username>/web/dl2-datafi/node_modules/arcgis-js-api/views/2d/layers/features/Pipeline

image

Theres a few concerns here:

  • First the obvious one is my app won't load. That makes me sad.
  • Second the username of my account is actually getting put into the ouput build, which I'm not a big fan of either.

If you have any thoughts, I'd love to hear them.

Packages Version
Webpack: 4.24.0
Dojo-webpack-plugin: 2.7.6
ArcGIS webpack plugin: 4.9.0
Dojo: 1.14.0
arcgis-js-api: 4.9.3

Dojo.config:

{
    "hasCache": {
        "webpack": 1,
        "host-browser": 1,
        "dom": 1,
        "dojo-loader": 1,
        "dojo-has-api": 1,
        "dojo-dom-ready-api": 1,
        "dojo-sniff": 1,
        "dojo-test-sniff": 1,
        "config-deferredInstrumentation": false,
        "config-tlmSiblingOfDojo": 1,
        "dojo-config-api": 0,
        "esri-promise-compatibility": 1,
        "esri-webpack": 1,
        "dom-addeventlistener": true,
        "touch-events": false,
        "pointer-events": true,
        "device-width": 1536,
        "dom-attributes-explicit": true,
        "dom-attributes-specified-flag": false,
        "extend-dojo": 1,
        "dojo-guarantee-console": 1,
        "dojo-debug-messages": false,
        "dojo-modulePaths": 1,
        "dojo-moduleUrl": 1,
        "air": false,
        "webkit": 537.36,
        "chrome": 70,
        "mac": false,
        "quirks": false,
        "svg": true,
        "dom-contains": true,
        "css-user-select": "userSelect",
        "json-parse": true,
        "json-stringify": true,
        "event-stopimmediatepropagation": true,
        "config-useDeferredInstrumentation": false,
        "activex": false,
        "dojo-force-activex-xhr": false,
        "dojo-preload-i18n-Api": 1,
        "dojo-v1x-i18n-Api": 1,
        "esri-secure-context": false,
        "esri-wasm": true,
        "esri-workers": true,
        "esri-url-encodes-apostrophe": true,
        "esri-webgl": true,
        "esri-webgl-high-precision-fragment": true,
        "esri-webgl-vertex-shader-samplers": true,
        "esri-webgl-element-index-uint": true,
        "esri-webgl-standard-derivatives": true,
        "esri-webgl-instanced-arrays": true,
        "esri-webgl-major-performance-caveat": false,
        "esri-featurelayer-webgl": true,
        "esri-featurelayer-webgl-labeling": true,
        "esri-webgl2": true,
        "dojo-config-addOnLoad": 1,
        "dom-quirks": false,
        "events-mouseenter": true,
        "events-mousewheel": true,
        "events-keypress-typed": true,
        "config-selectorEngine": "acme",
        "dom-qsa2.1": true,
        "dom-matches-selector": true,
        "dom-qsa": true,
        "dojo-config-require": 1,
        "esri-promise-compatibility-deprecation-warnings": true,
        "dijit-legacy-requires": false,
        "dojo-bidi": false,
        "highcontrast": false,
        "esri-workers-arraybuffer-transfer": true,
        "esri-svg-classlist": true
    },
    "paths": {},
    "pathsMapProg": [],
    "packs": {
        "dojo": {
            "main": "main",
            "name": "dojo",
            "location": "./dojo",
            "lib": "."
        },
        "dijit": {
            "main": "main",
            "name": "dijit",
            "location": "./dijit",
            "lib": "."
        },
        "dojox": {
            "main": "main",
            "name": "dojox",
            "location": "./dojox",
            "lib": "."
        },
        "esri": {
            "main": "kernel",
            "name": "esri",
            "location": "./arcgis-js-api"
        },
        "@dojo": {
            "main": "main",
            "name": "@dojo",
            "location": "./@dojo",
            "lib": "."
        },
        "cldrjs": {
            "main": "dist/cldr",
            "name": "cldrjs",
            "location": "./cldrjs"
        },
        "globalize": {
            "main": "dist/globalize",
            "name": "globalize",
            "location": "./globalize"
        },
        "tslib": {
            "main": "tslib",
            "name": "tslib",
            "location": "./tslib"
        },
        "moment": {
            "main": "main",
            "name": "moment",
            "location": "./moment",
            "lib": "."
        },
        "dstore": {
            "main": "main",
            "name": "dstore",
            "location": "./dojo-dstore",
            "lib": "."
        },
        "maquette": {
            "main": "dist/maquette.umd",
            "name": "maquette",
            "location": "./maquette",
            "resourceTags": {}
        },
        "maquette-css-transitions": {
            "main": "dist/maquette-css-transitions.umd",
            "name": "maquette-css-transitions",
            "location": "./maquette-css-transitions",
            "resourceTags": {}
        },
        "maquette-jsx": {
            "main": "dist/maquette-jsx.umd",
            "name": "maquette-jsx",
            "location": "./maquette-jsx",
            "resourceTags": {}
        }
    },
    "aliases": [],
    "mapProgs": [
        ["globalize", [
            ["cldr/supplemental", "cldrjs/dist/cldr/supplemental", {}, 17],
            ["cldr/unresolved", "cldrjs/dist/cldr/unresolved", {}, 15],
            ["cldr/event", "cldrjs/dist/cldr/event", {}, 10],
            ["cldr", "cldrjs/dist/cldr", {}, 4]
        ], {}, 9]
    ],
    "modules": {},
    "cache": {},
    "locale": "en-us",
    "baseUrl": "./",
    "afterOnLoad": true
}

Webpack config:

const ArcGISPlugin = require('@arcgis/webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');
const MinifyPlugin = require('terser-webpack-plugin');

module.exports = {
    entry: {
        'main': './src/index.js',
    },
    output: {
        filename: '[name].[chunkhash].js',
        publicPath: '',
    },

    plugins: [
        new CleanWebpackPlugin(['dist', 'build']),
        new ArcGISPlugin({
            useDefaultAssetLoaders: false,
        }),
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename: './[name].[hash].css',
            chunkFilename: './[id].[hash].css',
        }),
        new HtmlWebPackPlugin({
            template: './src/index.html',
            filename: './index.html',
            chunksSortMode: 'none',
        }),
        new HtmlWebPackPlugin({
            inject: false,
            template: './src/oauth-callback.html',
            filename: './oauth-callback.html',
            chunksSortMode: 'none',
        }),
    ],

    module: {
        rules: [{
            test: /\.stache$/,
            use: [{loader: 'raw-loader'}],
        }, {
            test: /\.layout$/,
            use: [{loader: 'raw-loader'}],
        }, {
            test: /\.js$/,
            exclude: /node_modules/,
            use: [{
                loader: 'babel-loader',
                options: {
                    sourceMap: true,
                },
            }],
        }, {
            test: /\.css$/,
            use: [
                MiniCssExtractPlugin.loader,
                {loader: 'css-loader', options: {sourceMap: true}},
                'postcss-loader', {
                    loader: 'resolve-url-loader',
                    options: {includeRoot: true},
                },
            ],
        }, {
            test: /\.less$/,
            use: [
                MiniCssExtractPlugin.loader,
                'css-loader',
                'postcss-loader',
                'less-loader',
            ],
        }, {
            test: /\.scss$/,
            use: [
                MiniCssExtractPlugin.loader,
                {loader: 'css-loader', options: {sourceMap: true}},
                'postcss-loader', {
                    loader: 'resolve-url-loader',
                    options: {includeRoot: true, sourceMap: true},
                }, {
                    loader: 'sass-loader',
                    options: {
                        sourceMap: true,
                    },
                },
            ],
        }, {
            test: /\.(jpe?g|png|gif|webp)$/,
            loader: 'url-loader',
            options: {
                // Inline files smaller than 10 kB (10240 bytes)
                limit: 10 * 1024,
            },
        }, {
            test: /\.(wsv|ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
            use: [{
                loader: 'file-loader',
                options: {
                    name: 'build/[name].[ext]',
                },
            }],
        }],
    },


    resolve: {
        extensions: ['.wasm', '.js', '.json'],
        modules: [
            path.resolve(__dirname, '/src'),
            path.resolve(__dirname, 'node_modules/'),
        ],
        alias: {
            'esri': 'arcgis-js-api',
            'sweetalert2$': 'sweetalert2/dist/sweetalert2',
            'moment': 'moment/moment',
        },
    },


    node: {
        process: false,
        global: false,
        fs: 'empty',
    },


    externals: [
        (context, request, callback) => {
            if (/pe-wasm$/.test(request)) {
                return callback(null, 'amd ' + request);
            }
            callback();
        },
    ],

    optimization: {
        minimizer: [
            new MinifyPlugin({
                parallel: true,
            }),
        ],
    },
};

EsriConfig.js for workers:

import esriConfig from 'esri/config';

const DEFAULT_WORKER_URL = 'https://js.arcgis.com/4.9/';
const DEFAULT_LOADER_URL = `${DEFAULT_WORKER_URL}dojo/dojo-lite.js`;

esriConfig.workers.loaderUrl = DEFAULT_LOADER_URL;
esriConfig.workers.loaderConfig = {
    baseUrl: `${DEFAULT_WORKER_URL}dojo`,
    has: {
        'esri-featurelayer-webgl': 1,
    },
    packages: [
        {name: 'esri', location: `${DEFAULT_WORKER_URL}esri`},
        {name: 'dojo', location: `${DEFAULT_WORKER_URL}dojo`},
        {name: 'dojox', location: `${DEFAULT_WORKER_URL}dojox`},
        {name: 'dstore', location: `${DEFAULT_WORKER_URL}dstore`},
        {name: 'moment', location: `${DEFAULT_WORKER_URL}moment`},
        {name: '@dojo', location: `${DEFAULT_WORKER_URL}@dojo`},
        {
            name: 'cldrjs',
            location: `${DEFAULT_WORKER_URL}cldrjs`,
            main: 'dist/cldr',
        },
        {
            name: 'globalize',
            location: `${DEFAULT_WORKER_URL}globalize`,
            main: 'dist/globalize',
        },
        {
            name: 'maquette',
            location: `${DEFAULT_WORKER_URL}maquette`,
            main: 'dist/maquette.umd',
        },
        {
            name: 'maquette-css-transitions',
            location: `${DEFAULT_WORKER_URL}maquette-css-transitions`,
            main: 'dist/maquette-css-transitions.umd',
        },
        {
            name: 'maquette-jsx',
            location: `${DEFAULT_WORKER_URL}maquette-jsx`,
            main: 'dist/maquette-jsx.umd',
        },
        {name: 'tslib', location: `${DEFAULT_WORKER_URL}tslib`, main: 'tslib'},
    ],
};

Related:

Esri/arcgis-webpack-plugin#22
https://stackoverflow.com/questions/51986624/webpack-babel-loader-outputting-full-c-drive-urls-in-bundles/52007420#52007420

Memory leak in watch mode

When using webpack in watch mode (or with webpack-dev-server) the plugin causes a massive memory leak.

I think the offending code is at least in DojoLoaderPlugin.js and DojoAMDModuleFactoryPlugin.js.

tap(compiler, "compilation", (compilation, params) => {
	const context = Object.create(this, {
		compilation:{value: compilation},
		params:{value: params}
	});

	// later (for example)
	tap(compiler, "make", this.validateEmbeddedLoader, context);
});

This causes each compilation object to be retained by the compiler object (to be used as this for the hook). Since each compilation contains compiled assets, this may leak several MBs after each incremental compilation run.

Another side effect is that the old hooks stay around and are executed, gradually slowing down webpack and possibly causing unintended behavior.

I don't know how to fix this quickly. We should either refactor the plugin to not rely on the state being carried along the hook function, or we should find a clever hack to "unregister" the stale hooks, which is something not allowed by tapable out of the box.

dijit/Fieldset.js + css2

First of all I would like to say a very big thank you for your work in this package - it has added a new lease of life to the whole dojo ecosystem for us!

The issue I am seeing is whenever dijit/Fieldset is referenced within a widget, we get the following webpack issue:

ERROR in ./node_modules/dijit/Fieldset.js
Module not found: Error: Can't resolve 'css2' in '/home/gordon/git/HPCC-Platform/esp/src/node_modules/dijit'
 @ ./node_modules/dijit/Fieldset.js 1:0-41:2
 @ ./eclwatch/LZBrowseWidget.js
 @ ./eclwatch/Utility.js
 @ ./eclwatch/stub.js

It also looks like there may be several similar occurrences within dijit...

Error when using plugin

Hi,

I get the following error when trying to use the loader:

Error: No hook for resolver normal in object ResolverFactory
at names.forEach.name (/Users/Klaus/git/matc_ui/node_modules/webpack-plugin-compat/lib/pluginCompatV4.js:101:11)
at Array.forEach ()
at events.forEach.event (/Users/Klaus/git/matc_ui/node_modules/webpack-plugin-compat/lib/pluginCompatV4.js:98:9)
at Array.forEach ()
at Object.tap (/Users/Klaus/git/matc_ui/node_modules/webpack-plugin-compat/lib/pluginCompatV4.js:93:9)
at DojoAMDResolverPluginV4.apply (/Users/Klaus/git/matc_ui/node_modules/dojo-webpack-plugin/lib/DojoAMDResolverPluginV4.js:28:3)
at applyResolverPlugin (/Users/Klaus/git/matc_ui/node_modules/dojo-webpack-plugin/lib/compat.js:70:39)
at DojoAMDPlugin.apply (/Users/Klaus/git/matc_ui/node_modules/dojo-webpack-plugin/lib/DojoAMDPlugin.js:48:3)
at webpack (/Users/Klaus/git/matc_ui/node_modules/webpack/lib/webpack.js:47:13)
at processOptions (/Users/Klaus/git/matc_ui/node_modules/webpack-cli/bin/cli.js:441:16)
at yargs.parse (/Users/Klaus/git/matc_ui/node_modules/webpack-cli/bin/cli.js:536:3)
at Object.parse (/Users/Klaus/git/matc_ui/node_modules/yargs/yargs.js:567:18)
at /Users/Klaus/git/matc_ui/node_modules/webpack-cli/bin/cli.js:219:8
at Object. (/Users/Klaus/git/matc_ui/node_modules/webpack-cli/bin/cli.js:538:3)
at Module._compile (internal/modules/cjs/loader.js:721:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
at Module.require (internal/modules/cjs/loader.js:657:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object. (/Users/Klaus/git/matc_ui/node_modules/webpack/bin/webpack.js:155:2)
at Module._compile (internal/modules/cjs/loader.js:721:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:774:12)
at executeUserCode (internal/bootstrap/node.js:342:17)
at startExecution (internal/bootstrap/node.js:276:5)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] buildDev: rm -rf dist && webpack --mode development --config webpack.server.config.js && webpack --mode development --config webpack.dev.config.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] buildDev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:

Cannot read property 'replace' of undefined on build

This is related to: OpenNTF/dojo-webpack-plugin-sample#72
I did not know whether it is a dojo-webpack-plugin issue or the sample code which is erroneous.

So basically running the sample you provided, I get a:

ERROR in chunk main [entry]
bundle.js
/Users/tbeyer/Sites/playground/stuff/dojo-webpack-plugin-sample-master/node_modules/dojo/_base/lang.js
Cannot read property 'replace' of undefined

ERROR in chunk 1
1.bundle.js
/Users/tbeyer/Sites/playground/stuff/dojo-webpack-plugin-sample-master/node_modules/dojox/charting/plot2d/Default.js
Cannot read property 'replace' of undefined

ERROR in chunk 2
2.bundle.js
/Users/tbeyer/Sites/playground/stuff/dojo-webpack-plugin-sample-master/node_modules/dijit/Calendar.js
Cannot read property 'replace' of undefined

ERROR in chunk 3
3.bundle.js
/Users/tbeyer/Sites/playground/stuff/dojo-webpack-plugin-sample-master/node_modules/dijit/Editor.js
Cannot read property 'replace' of undefined

ERROR in chunk 4
4.bundle.js
/Users/tbeyer/Sites/playground/stuff/dojo-webpack-plugin-sample-master/node_modules/dijit/ColorPalette.js
Cannot read property 'replace' of undefined

Thanks for your help

Duplicate absMid for some modules

I have a module that uses babel-runtime (6) and @babel/runtime (7) and it was running into some issues with duplicate absMid

Duplicate absMid ("core-js/library/fn/number/max-safe-integer") for modules "/home/cdiesh/src/jbrowse/node_modules/@babel/runtime-corejs2/node_modules/core-js/library/fn/number/max-safe-integer.js" and "/home/cdiesh/src/jbrowse/node_modules/babel-runtime/node_modules/core-js/library/fn/number/max-safe-integer.js"

Is it possible to work around this bug? I also noticed that I was getting duplicate absMid when I did "yarn link" setups similar to this, but this is the first time I noticed the bug that is unresolvable due to mixing babel 6 and 7.

Currently using 2.7.7, can try and make a reproducible example if it helps

Incorrect output when using ProvidePlugin together with DojoWebpackPlugin

I downloaded the dojo-webpack-plugin-sample and added one line in LazyContentPane.js that uses jquery:
var body = $('body');
I added the ProvidePlugin to map $ to jquery in webpack.config.js:
new webpack.ProvidePlugin({ $: 'jquery' })
and added jquery to the project:
npm install --save-dev [email protected]

Now, when I build the project the generated output contains incorrect output at the place where ProvidePlugin tries to insert the $ variable to resolve to jquery (output simplified by removing lots of duplicate lines):

/* WEBPACK VAR INJECTION */(function($) { var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; !(__WEBPACK_AMD_DEFINE_ARRAY__ = !(module.exports = , __WEBPACK_AMD_DEFINE_RESULT__ = i.apply(null, __WEBPACK_AMD_DEFINE_ARRAY__),

I tried to reproduce this without DojoWebPackPlugin, but then it works correctly.

Support require() without callback ("Cannot read property 'apply' of undefined" error)

My project uses ASP.NET views which load their Dojo page content by importing the component in a script tag:

<script type="text/javascript">
  require(["abc/editor"]);
</script>

I'm pretty sure that using require in this way (without a callback function) is valid. Doing this under dojo-webpack-plugin however causes an error: "Uncaught TypeError: Cannot read property 'apply' of undefined". The offending snippet is in DojoAMDMainTemplate.runtime.js; looks like it just needs to check that callback is defined before executing it.

In the meantime there's a natural workaround of passing an empty function:

<script type="text/javascript">
  require(["abc/editor"], function() {});
</script>

Happy to put up a PR once I'm home and reunited with my SSH key.

Bundling Error while loading JSON with dojo/text

Hi,

I'm stuck with the following error while bundling, wenn I try to load a JSON file with dojo/text:

ERROR in ./source/json/config.json (./node_modules/dojo-webpack-plugin/loaders/dojo/text!./source/json/config.json)
Module parse failed: Unexpected token m in JSON at position 0 while parsing near 'module.exports = "{\...'
File was processed with these loaders:
 * ./node_modules/dojo-webpack-plugin/loaders/dojo/text/index.js
You may need an additional loader to handle the result of these loaders.
SyntaxError: Unexpected token m in JSON at position 0 while parsing near 'module.exports = "{\...'
    at JSON.parse (<anonymous>)
    at parseJson (C:\example\build\node_modules\json-parse-better-errors\index.js:7:17)
    at JsonParser.parse (C:\example\build\node_modules\webpack\lib\JsonParser.js:16:16)
    at doBuild.err (C:\example\build\node_modules\webpack\lib\NormalModule.js:482:32)
    at runLoaders (C:\example\build\node_modules\webpack\lib\NormalModule.js:358:12)
    at C:\example\build\node_modules\loader-runner\lib\LoaderRunner.js:373:3
    at iterateNormalLoaders (C:\example\build\node_modules\loader-runner\lib\LoaderRunner.js:214:10)
    at iterateNormalLoaders (C:\example\build\node_modules\loader-runner\lib\LoaderRunner.js:221:10)
    at C:\example\build\node_modules\loader-runner\lib\LoaderRunner.js:236:3
    at runSyncOrAsync (C:\example\build\node_modules\loader-runner\lib\LoaderRunner.js:130:11)
    at iterateNormalLoaders (C:\example\build\node_modules\loader-runner\lib\LoaderRunner.js:232:2)
    at Array.<anonymous> (C:\example\build\node_modules\loader-runner\lib\LoaderRunner.js:205:4)
    at Storage.finished (C:\example\build\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:43:16)
    at provider (C:\example\build\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:79:9)
    at C:\example\build\node_modules\graceful-fs\graceful-fs.js:115:16
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:511:3)
 @ ./source/js/mockup/config.js 

I'm not sure what the message "You may need an additional loader to handle the result of these loaders." should tell me.
Webpack-Loader, Dojo-Loader or something other?

This is the basic module for fetching the JSON:

define([
  'dojo/json',
  'dojo/text!json/config.json',
], function(JSON, configJson) {

// ...
// console.log(JSON.parse(configJson, true))
// ...

});

Note: The JSON.parse is commented out.

As far as I understand the loader dojo-webpack-plugin/loaders/dojo/text return an module.export which webpack tries to parse, which fails.

Does something went wrong or do I do something wrong?

Modules can't be found when using the commons chunk plugin

When using the commons chunk plugin, the call to registerAbsMids is after the loader actually attempts to resolve the modules in the chunk and fails. This can be seen in this branch of the sample app. It will build fine, but fails with an error that dojo/has cannot be found.

I've opened a PR that emits the call before the code and created another branch of the sample app that uses a tarball with this fix.

"Error: unavailable" in runner.js:29:9 when using dojo/domReady!

As soon I use dojo/domReady! within the define declaration I get an the following error:

Uncaught Error:  unavailable
    at runner.js:29
    at loaderProxy:2
    at Object.<anonymous> (loaderProxy:3)
    at u (bootstrap:19)
    at Object.<anonymous> (test.js:2)
    at u (bootstrap:19)
    at Object.<anonymous> (bootstrap.js:2)
    at u (bootstrap:19)
    at bootstrap:324
    at bundle.1570462823.js:1

boostrap.js:

define([
  'ui/test',
], function(
    Test
) {
  console.log('Test', Test);
});

ui/test.js

define([
  'dojo/domReady!',
], function(
) {
  return {
    property: 'Test',
  };
});

I tested this with the dojo-webpack-plugin-sample-master.

Before I could run the webpack build with dojo/domReady, I had to add the snippet to the webpackconfig as @chuckdumont mentioned in #167 (comment)

Maybe I have to follow @chuckdumont advice from #167 (comment):

Also, you should remove js-src from the resolveLoader modules so that webpack won't try to load any Dojo loader plugins as webpack loaders.

But I not sure what this means.

dojox.widget.ColorPicker resource files urls

Packaging a web app which contains an instance of dojox.widget.ColorPicker.

The webpacked bundle ends up including the entire URL to the build folder and not the relative path, so once deployed the URLs cannot be resolved:
Actual: http://192.168.3.22:8010/home/gordon/git/HPCC-Platform/esp/src/node_modules/dojox/widget/ColorPicker/images/pickerPointer.png
Expected: esp/src/node_modules/dojox/widget/ColorPicker/images/pickerPointer.png

Looking at the code it appears to be a possible general issue with: require.toUrl("x/y/z.png")

Webpack DLLPlugin

I don't know if this is really an issue, more of a question.

I am trying to utilize the Webpack DLLPlugin to build a manifest of my API. I don't know if it's a workflow thing or something else. The DLLPlugin samples make it look straight forward/

Here is where I create the DLLs using the sample app provided.

// dll.webpack.config.js
const DojoWebpackPlugin = require("dojo-webpack-plugin");
const path = require("path");
const webpack = require("webpack");

module.exports = {
  resolve: {
    extensions: [".js", ".css"]
  },
  entry: {
    commons: ["dojo/_base/lang", "dojo/_base/declare"],
    dijit: ["dijit/layout/TabContainer", "dijit/layout/ContentPane"]
  },
  output: {
    path: path.join(__dirname, "dist"),
    filename: "dojo.[name].js",
    library: "[name]_[hash]"
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, "dist", "[name]-manifest.json"),
      name: "[name]_[hash]"
    }),
		new DojoWebpackPlugin({
			loaderConfig: require("./js/loaderConfig"),
			environment: {dojoRoot: "dist"},	// used at run time for non-packed resources (e.g. blank.gif)
			buildEnvironment: {dojoRoot: "node_modules"}, // used at build time
			locales: ["en"]
		})
  ],
};

My DLLs get generated fine. I can check the output and see my dojo/dijit deps just fine.

Then I try to use them here.

// webpack.config.js
...
	plugins: [
		new webpack.DllReferencePlugin({
			context: path.join(__dirname, "..", "dist"),
			manifest: require("./dist/commons-manifest.json")
		}),
		new webpack.DllReferencePlugin({
			context: path.join(__dirname, "..", "dist"),
			manifest: require("./dist/dijit-manifest.json")
		}),
		new DojoWebpackPlugin({
			loaderConfig: require("./js/loaderConfig"),
			environment: {dojoRoot: "dist"},	// used at run time for non-packed resources (e.g. blank.gif)
			buildEnvironment: {dojoRoot: "node_modules"}, // used at build time
			locales: ["en"]
		})
        ],
...

No errors, but the DLLs don't seem to get utilized. I've tried switching the order of DLL refs and dojo-webpack-plugin around and no luck.

I was expecting that Webpack would see the output the dojo-webpack-plugin is passing into the build and utilize the DLLs, but maybe that's not how it works.

I was curious if there was something I was missing related to the dojo-webpack-plugin and how it's used or if anyone has tried this before.

Thanks!

runtime require inconsistency

<edit - I initially thought this was an IE11 issue, but I can reproduce in chrome>

Opening the sample application test page fails when locale is set to en-gb (https://openntf.github.io/dojo-webpack-plugin-sample/test.html):

Error: Module not found: dojo/cldr/nls/en-gb/gregorian
   {
      [functions]: ,
      __proto__: { },
      description: "Module not found: dojo/cldr/nls/en-gb/gregorian",
      message: "Module not found: dojo/cldr/nls/en-gb/gregorian",
      name: "Error",
      stack: "Error: Module not found: dojo/cldr/nls/en-gb/gregorian
   at d (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:895)
   at Anonymous function (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:1294)
   at l (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:1265)
   at i (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:123)
   at Anonymous function (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:102282)
   at l (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:1265)
   at i (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:123)
   at g (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:102212)
   at Anonymous function (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:102947)
   at s.forEach (https://openntf.github.io/dojo-webpack-plugin-sample/release/bundle.js:1:15942)"
   }

Steps to reproduce:
Add the following locale override to dojo config:

        locale: "en-gb",        

Rebuild and open.

There are two issue going on, the missing locale is covered by: https://github.com//issues/69 and this issue will focus on the inconsistent behaviour of the runtime require call.

cannot read property addchunk

Hi, Thanks for your great job.
but i use html-webpack-plugin with dojo-webpack-plugin, something wrong:
“cannot read property addchunk”

Erros while processing dojo plugins

I'm trying to bundle our dojo application using dojo-webpack-plugin. While compiling I get errors for places where we use dojo plugins:

Module not found: Error: Can't resolve 'dojo/domReady' in ...
Module not found: Error: Can't resolve 'raw-loader' in ...

(where the raw-loader is actually dojo/text! in the original source code).

Also for some custom plugins that we created, the same error occurs. How should we deal with this?

Error with Webpack >=4.18.1: "No hook for resolver normal in object ResolverFactory"

I'm getting an error on build after upgrading from webpack 4.16.2 to 4.23.0. After narrowing it down, it appears that 4.18.0 is the last version that's working for me, and 4.18.1 is the first version where it breaks. I do not envy you guys for using an API that breaks on a patch-version release...

Build error:

> webpack --progress --watch --info-verbosity verbose --mode=development --env.NODE_ENV=development --config build/webpack.config.js


D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:101
                                throw new Error(`No hook for ${name} in object ${obj.constructor.name}`);
          ^
Error: No hook for resolver normal in object ResolverFactory
    at names.forEach.name (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:101:11)
    at Array.forEach (<anonymous>)
    at events.forEach.event (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:98:9)
    at Array.forEach (<anonymous>)
    at Object.tap (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-plugin-compat\lib\pluginCompatV4.js:93:9)
    at DojoAMDResolverPluginV4.apply (D:\Code\RC-Reporter\ReporterClient\node_modules\dojo-webpack-plugin\lib\DojoAMDResolverPluginV4.js:28:3)
    at applyResolverPlugin (D:\Code\RC-Reporter\ReporterClient\node_modules\dojo-webpack-plugin\lib\compat.js:70:39)
    at DojoAMDPlugin.apply (D:\Code\RC-Reporter\ReporterClient\node_modules\dojo-webpack-plugin\lib\DojoAMDPlugin.js:48:3)
    at webpack (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack\lib\webpack.js:47:13)
    at processOptions (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-cli\bin\cli.js:441:16)
    at yargs.parse (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-cli\bin\cli.js:536:3)
    at Object.parse (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-cli\node_modules\yargs\yargs.js:563:18)
    at D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-cli\bin\cli.js:219:8
    at Object.<anonymous> (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack-cli\bin\cli.js:538:3)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (D:\Code\RC-Reporter\ReporterClient\node_modules\webpack\bin\webpack.js:155:2)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3

Dojo loader config:

{
        baseUrl: env.dojoRoot,
        blankGif: '/rcr-src/dist/images/blank.gif',
        extraLocale: ['en-us'],
        isDebug: env.isDebug,
        packages: [
            { name: 'dgrid', location: env.dojoRoot + '/RCDGrid/dgrid', lib: '.' },
            { name: 'dijit', location: env.dojoRoot + '/DojoToolkit/dijit', lib: '.' },
            { name: 'dojo', location: env.dojoRoot + '/DojoToolkit/dojo', lib: '.' },
            { name: 'dojox', location: env.dojoRoot + '/DojoToolkit/dojox', lib: '.' },
            { name: 'put-selector', location: env.dojoRoot + '/RCDGrid/put-selector', lib: '.' },
            { name: 'rc', location: env.dojoRoot + '/rc', lib: '.' },
            { name: 'xstyle', location: env.dojoRoot + '/RCDGrid/xstyle', lib: '.' },
            { name: 'FusionCharts', location: env.dojoRoot + '/FusionCharts', lib: '.'}
        ],
    };

Webpack plugin config:

            new DojoWebpackPlugin({
                // The Dojo loader configuration. By importing it instead of defining it inline, we can use the
                // `environment` and `buildEnvironment` options below to alter the loader config at run-time vs at
                // build-time.
                loaderConfig: require("./dojoLoaderConfig"),
                environment: { dojoRoot: "/rcr-src", isDebug },
                buildEnvironment: { dojoRoot: legacyRoot, isDebug },
                noConsole: true,
            }),

Unable to resolve custom widgets with "/" in their namespace, only "." works.

Very simple issue I encountered with my custom widgets.

  1. This works:
    <div data-dojo-type="myapp.CustomWidget"></div>
  2. This doesn't work:
    <div data-dojo-type="myapp/CustomWidget"></div>

Dojo docs have said to use the second form for a while though. Even weirder, the dojo-webpack-loader is fine with the newer for built-in dijits, so this works:

<div data-dojo-type="dijit/layout/TabContainer" style="width: 100%; height: 400px;">

Made an easy test case: https://github.com/wmakley/dojo-webpack-plugin-sample

Seems to be some issue with the parser, but it's quite soupy for me to "parse". Even with this bug the experience of using this loader is 500% better than the "dojo build tool" so I will probably just replace all my widget references for now. Thank you for your hard work!

Error: Dojo loader version does not match the version of Dojo.

Could someone please help me to figure out why I'm getting this error:
Error: Dojo loader version does not match the version of Dojo. Loader version = 1.15.0. Dojo version = 0.0.1.
Problem is that it takes Dojo version from my package.json, which doesn't seem to be a right place.

If I change version in package.json - everything works fine.

Thanks in advance!

Packages not loaded from defined location

In the dojoLoader configuration we define the following packages:

  { name: 'lodash', location: 'xxx/libraries/lodash', main: 'lodash' },
  { name: 'postal', location: 'xxx/libraries/postal', main: 'lib/postal' },
  { name: 'postal.federation', location: 'xxx/libraries/postal.federation', main: 'lib/postal.federation' },
  { name: 'postal.xframe', location: 'xxx/libraries/postal.xframe', main: 'lib/postal.xframe' },

Lodash is not added as a dependency in our package.json file. node_modules directory contains lodash.

When loading the application the postal.xframe library loads lodash from node_modules directory where it should load from 'xxx/libraries/lodash' (that is what we configured...).
When I add lodash as a dependency in package.jon, lodash is loaded from 'xxx/libraries/lodash'.

How can we we make sure that lodash is loaded from the location that is defined in the dojoLoader configuration?

Regex in config aliases exported as empty object

When specifying the loader config as an object or function, if an alias definition in the config contains a regex, then when the config is exported to the client, the regex is an empty object

No solution with dynamic Dojo/Require

Hello everybody, i hope you will see my issue.

I have a very big problem with the common problem (DYNAMIC REQUIRE) but now it’s about dojo require, i use arcgis-webpack-plugin that utilizes dojo-webpack-plugin
i have tried the code splitting webpack, not working
the lazy loading not working
i have tried libraryTarget :’amd’ same thing ..

here is my code

in the config i use the simple configuration of arcgisPlugin

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const ArcGISPlugin = require('@arcgis/webpack-plugin');


module.exports = {
 entry: {
   index: './src/js/importing.js'
 },
 output: {
   filename: '[name].bundle.js',
   path: path.resolve(__dirname, '../dist')
 },
 module: {
   rules: [
     {
       test: [/.js$/],
       exclude: /(node_modules)/,
       use: {
         loader: 'babel-loader',
         options: {
           presets: ['@babel/preset-env']
         }
       }
     },
     {
       test: /\.html$/,
       use: [
         {
           loader: 'html-loader',
           options: { minimize: true }
         }
       ]
     },
     {
       test: [/.css$|.scss$/],
       use: [
         {
           loader: MiniCssExtractPlugin.loader
         },
         'css-loader',
         'sass-loader',
         'postcss-loader'
       ]
     },
     {
       test: /\.(png|jpg|gif|svg)$/,
       use: [
         {
           loader: 'file-loader',
           options: {
             name: '[name].[ext]',
             outputPath: 'assets/images'
           }
         }
       ]
     },
     {
       test: /\.(wsv|ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
       use: [
         {
           loader: 'file-loader',
           options: {
             name: 'build/[name].[ext]'
           }
         }
       ]
     },
     {
       test: /\.js$/,
       loader: 'dojo-webpack-loader',
       include: path.resolve(__dirname, '../dojo/')
     }
   ]
 },

 plugins: [
   new CleanWebpackPlugin(),
   new ArcGISPlugin({
     useDefaultAssetLoaders: false
   }),
   new MiniCssExtractPlugin({
     filename: 'style.[chunkhash].css'
   }),
   new HtmlWebpackPlugin({
     title: 'lifadmin',
     template: './src/index.html',
     chunksSortMode: 'none',
     minify: {
       removeComments: true,
       collapseWhitespace: false
     }
   }),
   new CopyWebpackPlugin([
     {
       from: './src/assets/images',
       to: 'assets/images'
     }
   ])

 ],

 resolve: {
   modules: [path.resolve(__dirname, '/src'), 'node_modules/'],
   extensions: ['.js', '.scss']
 },


 node: {
   process: false,
   global: false,
   fs : 'empty'
 }
};

here i’m importing the scss and the config arcgis and my main file application and calling the startup function

importing.js

define([
"./main",   
'./config/arcgisConfig',
'../scss/main.scss'], function (main) {
   main.startup();
});

here, i would like to create list of widgets for future configuration and importing each one in the (require dojo)

main.js

define(["require"], function (require) {

   return {

       startup: function () {
           this.initWidgets();
       },

       initWidgets: function () {
           let listWidgets = {
               menu:
               {
                   type: 'simple',
                   title: 'Example',
                   icon: '<i class="fas fa-pencil-alt"></i>',
                   widget: {
                       path: './exampleWidget'
                   }
               }
           };

           require([(listWidgets.menu.widget.path)], Widget => {
               let construction = new Widget();
           });
       },

   }
});

the widget with template simple div !

exampleWidget.js

define([
   'dojo/_base/declare',
   'dijit/_WidgetBase',
   'dijit/_TemplatedMixin',

 ], function(declare, _WidgetBase, _TemplatedMixin, ) {
   return declare([_WidgetBase, _TemplatedMixin], {
     templateString: '<div>Hello Widget</div>',
     startup() {
       this.inherited(arguments);
     }
   });
 });

i get this error

Uncaught (in promise) Error: Module not found: src/js/exampleWidget
at findModule (index.bundle.js:167)
at contextRequire (index.bundle.js:193)
at result (index.bundle.js:108)
at eval (main.js:18)

how can i resolve this ?.. I just created a repo github for testing if you want

##THE LINK
https://github.com/dvbouali/test-arcgis-webpack

Build error when using ExtractTextPlugin

Thanks for creating this, it's really awesome!

I have a large application that is mostly Dojo AMD modules and partly React with ES6 modules that I'm trying to build with a single webpack configuration. However I'm getting a build error when I try to extract the CSS using extract-text-webpack-plugin.

The ES6 modules import CSS and Sass like this:

import "./styles.css";

My webpack configuration looks like this (only showing part of it here):

module: {
    rules: [
        {
            test: /\.jsx?$/,
            loader: "babel-loader"
        },
        {
            test: /\.css$/,
            loader: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: "css-loader"
            })
        }
    ]
},
plugins: [
    new DojoWebpackPlugin({
        loaderConfig,
        locales: ["en"],
        loader: path.resolve(__dirname, "dojoLoader/dojo/dojo.js")
    }),
    // ... [other plugins are here]
    new ExtractTextPlugin({
        filename: "[name].css",
        allChunks: true
    })

I managed to reproduce this using your sample application by adding a CSS file, ES6 module and including the babel-loader. This is the build error:

ERROR in ./css/styles.css
Module build failed: ChunkRenderError: Can't locate /var/folders/v_/tz8d71393lv7fsr707gs81kc0000gn/T/tmp-26466Cucq95eqC3xG/dojo/dojo.js in compilation
    at Compilation.createChunkAssets (/Users/jason/Development/OpenNTF/dojo-webpack-plugin-sample/node_modules/webpack/lib/Compilation.js:1275:22)
    at sealPart2 (/Users/jason/Development/OpenNTF/dojo-webpack-plugin-sample/node_modules/webpack/lib/Compilation.js:629:10)
    at Compilation.applyPluginsAsyncSeries (/Users/jason/Development/OpenNTF/dojo-webpack-plugin-sample/node_modules/tapable/lib/Tapable.js:131:46)
    at Compilation.seal (/Users/jason/Development/OpenNTF/dojo-webpack-plugin-sample/node_modules/webpack/lib/Compilation.js:579:8)
    at applyPluginsParallel.err (/Users/jason/Development/OpenNTF/dojo-webpack-plugin-sample/node_modules/webpack/lib/Compiler.js:514:17)
    at /Users/jason/Development/OpenNTF/dojo-webpack-plugin-sample/node_modules/tapable/lib/Tapable.js:225:11
    at _addModuleChain (/Users/jason/Development/OpenNTF/dojo-webpack-plugin-sample/node_modules/webpack/lib/Compilation.js:481:11)
    at processModuleDependencies.err (/Users/jason/Development/OpenNTF/dojo-webpack-plugin-sample/node_modules/webpack/lib/Compilation.js:452:13)
    at _combinedTickCallback (internal/process/next_tick.js:95:7)
    at process._tickCallback (internal/process/next_tick.js:161:9)
 @ ./js/es6module.js 6:0-28
 @ ./js/LazyContentPane.js
 @ ./js/bootstrap.js

If it would help I can provide my version of the sample application that I used to reproduce the error. If you can provide any help or point me in the right direction that would be great thanks.

Module build failed: ReferenceError: define is not defined

I am having problems making my bundle, every try ends with:

ERROR in ./js-src/dojo/domReady.js
Module build failed: ReferenceError: define is not defined
at Object. (/srv/ledgersmb/UI/js-src/dojo/domReady.js:1:63)
at Module._compile (/var/www/node_modules/v8-compile-cache/v8-compile-cache.js:178:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
at Module.load (internal/modules/cjs/loader.js:589:32)
at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
at Function.Module._load (internal/modules/cjs/loader.js:520:3)
at Module.require (internal/modules/cjs/loader.js:626:17)
at require (/var/www/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
at loadLoader (/var/www/node_modules/loader-runner/lib/loadLoader.js:13:17)
at iteratePitchingLoaders (/var/www/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
at runLoaders (/var/www/node_modules/loader-runner/lib/LoaderRunner.js:362:2)
at NormalModule.doBuild (/var/www/node_modules/webpack/lib/NormalModule.js:235:3)
at NormalModule.build (/var/www/node_modules/webpack/lib/NormalModule.js:365:15)
at Compilation.buildModule (/var/www/node_modules/webpack/lib/Compilation.js:362:10)
at factory.create (/var/www/node_modules/webpack/lib/Compilation.js:583:14)
at factory (/var/www/node_modules/webpack/lib/NormalModuleFactory.js:366:6)
at hooks.afterResolve.callAsync (/var/www/node_modules/webpack/lib/NormalModuleFactory.js:143:13)
at AsyncSeriesWaterfallHook.eval [as callAsync] (eval at create (/var/www/node_modules/tapable/lib/HookCodeFactory.js:24:12), :42:1)
at resolver (/var/www/node_modules/webpack/lib/NormalModuleFactory.js:126:29)
at resolver (/var/www/node_modules/dojo-webpack-plugin/lib/DojoAMDModuleFactoryPlugin.js:198:5)
at process.nextTick (/var/www/node_modules/webpack/lib/NormalModuleFactory.js:304:9)
at process._tickCallback (internal/process/next_tick.js:61:11)
@ ./js-src/webpack/bootstrap.js 16:0-21:2

My application is a Perl app with a Dojo based UI. The directory structure is:

app
+----- UI
        +----- js (Compiled dojo)
        +----- node_modules ( there for the moment, should be elsewhere )
        +----- js-src (Sources)
                   +----- dojo
                   +----- dijit
                   +----- util
                   +----- lsmb (our specific UI modules)
                   +----- webpack (webpack specifics)

The UI is made available to the web with a /js url. I cloned dojo-webpack-plugin-sample, which ran perfectly well here, and adjusted a bit.

webpack version is 4.8.1,
node, 10.1.0
dojo, 1.11.5

The application builds and run fine with Dojo loader, I am trying to move it to webpack to be able to add a few React pages.

The only real difference I found is the directory structure.

Here are my config files:
webpack.config.js.txt
loaderConfig.js.txt
bootstrap.js.txt

And the resulting log file
webpack.log.txt

Build fails with Webpack 4.19.1

The build fails with Webpack 4.19.1. The stack trace below. The issue can be seen here. Just run 'npm install' and 'npm run build'.

I think this issue is caused by the refactoring of 'webpack-sources' code. It changed the representation of replacements. See the relevant commit here.

The stack trace:

ERROR in chunk main [entry]
bundle.js
C:\P\git\dojo-webpack-plugin-sample\node_modules\dojo\_base\lang.js
Cannot read property 'replace' of undefined
TypeError: C:\P\git\dojo-webpack-plugin-sample\node_modules\dojo\_base\lang.js
Cannot read property 'replace' of undefined
    at source.replacements.forEach (C:\P\git\dojo-webpack-plugin-sample\node_modules\dojo-webpack-plugin\lib\DojoAMDDefineDependency.js:36:37)
    at Array.forEach ()
    at DojoAMDDefineDependencyTemplate.fixupDefineScope (C:\P\git\dojo-webpack-plugin-sample\node_modules\dojo-webpack-plugin\lib\DojoAMDDefineDependency.js:35:24)
    at DojoAMDDefineDependencyTemplate.apply (C:\P\git\dojo-webpack-plugin-sample\node_modules\dojo-webpack-plugin\lib\DojoAMDDefineDependency.js:30:8)
    at JavascriptGenerator.sourceDependency (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\JavascriptGenerator.js:151:12)
    at JavascriptGenerator.sourceBlock (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\JavascriptGenerator.js:44:9)
    at JavascriptGenerator.generate (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\JavascriptGenerator.js:23:8)
    at NormalModule.source (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\NormalModule.js:485:33)
    at ModuleTemplate.render (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\ModuleTemplate.js:54:32)
    at modules.map.module (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\Template.js:233:28)
    at Array.map ()
    at Function.renderChunkModules (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\Template.js:230:30)
    at compilation.mainTemplate.hooks.modules.tap (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\JavascriptModulesPlugin.js:86:23)
    at SyncWaterfallHook.eval [as call] (eval at create (C:\P\git\dojo-webpack-plugin-sample\node_modules\tapable\lib\HookCodeFactory.js:19:10), :7:16)
    at SyncWaterfallHook.lazyCompileHook (C:\P\git\dojo-webpack-plugin-sample\node_modules\tapable\lib\Hook.js:154:20)
    at MainTemplate.hooks.render.tap (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\MainTemplate.js:160:25)
    at SyncWaterfallHook.eval [as call] (eval at create (C:\P\git\dojo-webpack-plugin-sample\node_modules\tapable\lib\HookCodeFactory.js:19:10), :7:16)
    at SyncWaterfallHook.lazyCompileHook (C:\P\git\dojo-webpack-plugin-sample\node_modules\tapable\lib\Hook.js:154:20)
    at MainTemplate.render (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\MainTemplate.js:412:34)
    at Object.render (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\JavascriptModulesPlugin.js:65:34)
    at Compilation.createChunkAssets (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\Compilation.js:2364:29)
    at hooks.optimizeTree.callAsync.err (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\Compilation.js:1269:10)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\P\git\dojo-webpack-plugin-sample\node_modules\tapable\lib\HookCodeFactory.js:32:10), :6:1)
    at AsyncSeriesHook.lazyCompileHook (C:\P\git\dojo-webpack-plugin-sample\node_modules\tapable\lib\Hook.js:154:20)
    at Compilation.seal (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\Compilation.js:1214:27)
    at hooks.make.callAsync.err (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\Compiler.js:547:17)
    at _done (eval at create (C:\P\git\dojo-webpack-plugin-sample\node_modules\tapable\lib\HookCodeFactory.js:32:10), :9:1)
    at _err1 (eval at create (C:\P\git\dojo-webpack-plugin-sample\node_modules\tapable\lib\HookCodeFactory.js:32:10), :32:22)
    at _addModuleChain (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\Compilation.js:1065:12)
    at processModuleDependencies.err (C:\P\git\dojo-webpack-plugin-sample\node_modules\webpack\lib\Compilation.js:981:9)
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

Support for Dojo i18n resource files in webpack

Hello dojo-webpack-plugin team,

We are currently in the process of moving from Dojo based builds to webpack, and are trying to use your plugin to handle Dojo style AMD modules. Our localized resource files are stored in .js files and are formatted like so:

define({ root:
({
    Cancel: "Cancel",
    Commit: "Commit",
    versionLabel: "version"
}),
"it-it": true,
"ja-jp": true,
"ko-kr": true,
"zh-cn": true
});

Currently, our Dojo setup uses the localeList key in the profile.js file to support locales like:

localeList:'ja-jp,ko-kr,zh-cn,en-us,it-it', // this is working for Dojo build

Our webpack.config.js setup for the DojoWebpackPlugin looks like:

const DojoWebpackPlugin = require('dojo-webpack-plugin');
// ...
new DojoWebpackPlugin({
    loaderConfig: require(path.resolve(path_string + "/loaderConfig")),
    environment: {dojoRoot: "./release"}, 
    buildEnvironment: {dojoRoot: rootdir},
    locales: ["en", "ja", "ko", "zh"], // does not appear to be working for webpack build
    async: true
}),

With all of this configuration above, we have questions on how to properly get the dojo-webpack-plugin to handle our existing locales setup. Our webpack build passes, and we can load our application, but the webpack bundle created doesn't seem to have any information about the locales listed above. When the application is set to a supported locale, the expected resource strings are not loaded.

We are unclear as to where the localized files should exist, and how to verify that they have been bundled correctly.

Is there a setting that we might be missing?

dojo-webpack-plugin not working with IE11

After running the webpack build we cannot open our application in IE11, because IE11 does not support Object.assign.
Object.assign is used in DojoAMDMainTemplatePlugin.js.

Is it possible to change the code so that it also runs on IE11 or do you have another suggestion to make this work?

callback in dojo config not fired

Hey there, thanks for the plugin, if I get it to work, then it will be a game changer for that legacy dojo application of ours!

I’ll open several tickets I come across while trying to get this to work:

Unfortunately, I don’t get the dojo config callback to fire on client side:

dojoConfig = {
	...	
	callback: function() {
		console.log("foo");
	}
}

will not trigger the console.log

Or am I missing something?

Here is my example dojoConfig:

function getConfig(env) {
	// env is set by the 'buildEnvronment' and/or 'environment' plugin options (see webpack.config.js),
	// or by the code at the end of this file if using without webpack
	dojoConfig = {
		baseUrl: '.',
		packages: [
			{
				name: 'dojo',
				location: env.dojoRoot + '/dojo',
				lib: '.'
			},
			{
				name: 'dijit',
				location: env.dojoRoot + '/dijit',
				lib: '.'
			},
			{
				name: 'dojox',
				location: env.dojoRoot + '/dojox',
				lib: '.'
			},
			{
				name: 'dcd',
				location: env.srcRoot + '/dcd',
				lib: '.'
			}
		],

		paths: {
			js: "js",
			theme: "theme",
			// With the webpack build, the css loader plugin is replaced by a webpack loader
			// via webpack.config.js, so the following are used only by the unpacked app.
			css: "//chuckdumont.github.io/dojo-css-plugin/1.0.0/css",
			// lesspp is used by the css loader plugin when loading LESS modules
			lesspp: "//cdnjs.cloudflare.com/ajax/libs/less.js/1.7.3/less.min",
		},

		deps: ["src/dcd/js/bootstrap"],

		async: true,

		has: {"dojo-guarantee-console": 0},	// Don't need the config API code in the embedded Dojo loader
		
		callback: function() {
			console.log("foo");
		},

		fixupUrl: function(url) {
			// Load the uncompressed versions of dojo/dijit/dojox javascript files when using the dojo loader.
			// When using a webpack build, the dojo loader is not used for loading javascript files so this
			// property has no effect.  This is only needed because we're loading Dojo from a CDN for this
			// demo.  In a normal development envorinment, Dojo would be installed locally and this wouldn't
			// be needed.
			if (/\/(dojo|dijit|dojox)\/.*\.js$/.test(url)) {
			  url += ".uncompressed.js";
		  }
			return url;
		}
	};

	//for NON-build time only
	console.log("wow, what is it", env.runtime)
	if (env.runtime) {
		console.log("wow, it’s runtime")
		var urlParams = (function() {
			var tokens = window.location.search.substring(1).split("&");
			var params = {
				branding: window.branding
			};
	
			for (var i = 0; i < tokens.length; i++) {
				var next = tokens[i].split("=");
				params[next[0]] = next[1] || next[0];
			}
			return params;
		})();
	
		var cookieLang = (function() {
			var value = "; " + document.cookie;
			var parts = value.split("; language=");
			if (parts.length == 2) return parts.pop().split(";").shift();
		})();

		var userLocale = urlParams.lang || cookieLang || navigator.language || navigator.userLanguage || "";
		dojoConfig.locale = userLocale.indexOf("de") === 0 ? "de" : "en";
	}

	return dojoConfig;
}
// For Webpack, export the config.  This is needed both at build time and on the client at runtime
// for the packed application.
if (typeof module !== 'undefined' && module) {
	console.log("webpack");
	module.exports = getConfig;
} else {
	console.log("nowebpack");
	// No webpack.  This script was loaded by page via script tag, so load Dojo from CDN
	getConfig({dojoRoot: '//ajax.googleapis.com/ajax/libs/dojo/1.13.0'});
}

and in the webpack config:

const DojoWebpackPlugin = require("dojo-webpack-plugin");
var CopyWebpackPlugin = require("copy-webpack-plugin");
var UglifyJsPlugin = require("uglifyjs-webpack-plugin");

const path = require('path');
const webpack = require("webpack");

module.exports = {
    context: __dirname,
    entry: './src/dcd/index.js',
    output: {
        path: path.resolve(__dirname, 'target'),
        filename: 'bundle.js',
    },
    plugins: [
		new DojoWebpackPlugin({
			loaderConfig: path.resolve(__dirname, 'src/loaderConfig.js'),
			environment: {
				dojoRoot: "",
				runtime: true
			},	// used at run time for non-packed resources (e.g. blank.gif)
			buildEnvironment: {
                dojoRoot: "node_modules",
                srcRoot: "./src",
            }, // used at build time
			locales: ["en"],
			noConsole: false,
			coerceUndefinedToFalse: true
		}),

		// Copy non-packed resources needed by the app to the release directory
		new CopyWebpackPlugin([{
			context: "src",
			from: "*.html",
			to: ""
		}]),

		// For plugins registered after the DojoAMDPlugin, data.request has been normalized and
		// resolved to an absMid and loader-config maps and aliases have been applied
		new webpack.NormalModuleReplacementPlugin(/^dojox\/gfx\/renderer!/, "dojox/gfx/canvas"),
		new webpack.NormalModuleReplacementPlugin(
			/^css!/, function(data) {
				data.request = data.request.replace(/^css!/, "!style-loader!css-loader!less-loader!")
			}
		)
    ],
    resolveLoader: {
		modules: ["node_modules"]
    },
	mode: process.env.WEBPACK_SERVE ? 'development' : 'production',
	optimization: {
    minimizer: [
      // we specify a custom UglifyJsPlugin here to get source maps in production
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        uglifyOptions: {
          compress: true,
          mangle: true,
					output: {comments:false}
        },
        sourceMap: true
      })
    ]
  },
	devtool: "#source-map"
};

Workaround

I’m using dojo/ready as a workaround for the time being: https://dojotoolkit.org/reference-guide/1.10/dojo/ready.html

TypeError: Class constructor DojoAMDPlugin cannot be invoked without 'new'

The following code snippet is causing trouble with the latest NodeJS 6.11.3:

plugins: [
    new requre("dojo-webpack-plugin")({
        loaderConfig: require("./loaderConfig"),
        locales: ["en", "es", "fr"]
    }),
]

Error message:

    new require('dojo-webpack-plugin')({
                                      ^

TypeError: Class constructor DojoAMDPlugin cannot be invoked without 'new'

However, putting the plugin into a separate variable works:

const dojo_webpack_plugin = require('dojo-webpack-plugin')
...
plugins: [
    new dojo_webpack_plugin({
        loaderConfig: require("./loaderConfig"),
        locales: ["en", "es", "fr"]
    }),
    ...
]

Build error when dojo installed via npm

Hi there,

First off, thanks for the plugin, looks awesome!

I was able to get the sample app to work perfectly when I installed dojo libs via Bower into a libs folder and used npm run build --dojoRoot=libs. No issue there, and I think I actually did a little dance.

However, if I npm install the dojo modules and use npm run build --dojoRoot=node_modules I get multiple errors in reference to i18n and nls files that look like this.

ERROR in ./node_modules/dojo/i18n.js!./node_modules/dijit/node_modules/dojo/nls/colors.js
Module build failed: ReferenceError: define is not defined

I'm not sure if there is another config option I need to adjust or not.

Thanks!

nls + dojo calendar issue

Irrespective of what locales the user has specified in their DojoWebpackPlugin options, all locales must be included for the dojo calendar (dojo/cldr/nls).

I am guessing this is because the various calendars (dojo/cldr/nls/gregorian.js) reference them all specifically.

Steps to reproduce:

  • Build sample application with a subset of the locales it references (e.g. "en").
  • Open the sample app in a browser configured with "en-gb"

Note:

  • It won't fail if opened in a locale that it does not "know" about e.g. "en-ie".

Promises getting returned as resolved objects.

I am seeing this when I set 'async=true' for the dojo-webpack-plugin configuration in the webpack configuration.

Based on 6d1cf33, looks like it thinks the result of loading any file is not a promise. If it is a promise, it waits for the promise to the resolved and returns the resolved value to the requesting file. Doing this causes downstream code that expects promises to fail. So, is there a way to differentiate between "Loaders" (using the "!") and files that return a promise?

Project Compiles Twice

Description

In projects that have dojo-webpack-plugin, the code gets compiled twice when ran with webpack-dev-server. First noticed with arcgis-webpack-plugin that uses dojo-webpack-plugin (Esri/arcgis-webpack-plugin#54) under the covers but confirmed it occurs with just the use of dojo-webpack-plugin.

Expected Behavior

The code should only compile once.

Actual Behavior

Code is compiling twice (based on receiving two "Compiled successfully" messages) and in most cases a longer build/serve process.

Possible Fix

When testing with demo project, the dual compilation occurs. But with projects without the webpack plugins for arcgis or dojo, it doesn't happen.

Steps to Reproduce

  1. Use the code from https://github.com/OpenNTF/dojo-webpack-plugin-sample or https://github.com/Esri/jsapi-resources/tree/master/4.x/webpack/demo
  2. npm install
  3. npm run serve (for dojo project) or npm start (for arcgis project)
  4. Note in the resulting output that there are two "Compiled successfully" messages

Context

It's more of an annoyance than a big problem. Slows down the build. And when using bundle analysis and build notification plugins, it causes duplications of those tasks.

Your Environment

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.