AuraJS: Specifying dependencies between extensions - amd

I know it's possible to require other modules, but how can you tell aura to process a module as an extension?
Background:
For a large project I'm working on, I'm using aura extensions to modify a jQuery instance I'm keeping in the app's sandbox. A typical extension would look something like this, where plug1 and plug2 are jQuery plugins.
define({
require : {
paths : {
'jquery.plug1' : 'lib/plug1',
'jquery.plug2' : 'lib/plug2'
},
shim : {
'jquery.plug1' : {
exports : 'jQuery'
},
'jquery.plug2' : {
deps : ['jquery.plug1'],
exports : 'jQuery'
}
}
},
initialize : function(app) {
var $ = app.sandbox.$;
$ = require('jquery.plug1');
app.sandbox.$ = require('jquery.plug2');
}
});
For tightly coupled plugins I can specify dependencies as shown here, but I'd rather avoid this for more loosely coupled components.

Related

Webpack dev server: issue mapping paths local to remote. Output/bundle files load in IDE/Chrome

I'm trying to line up my dev server output with a local project for debugging. PhpStorm support couldn't find out what the issue was as we worked on it though.
The issue with the current config is that it seems to pull up the output / bundle file in the IDE, instead of keeping to the source code files.
I'm mapping "remote" urls to what I see in Chrome under sources > webpack > .
The result (see top left pane):
And before the above, the bundle file is the first stop in the debugger before I click resume (it opens on its own in the editor):
On the browser side, Chrome pauses script execution, but also jumps to the sources tab into a hard to read file, probably something compiled by webpack.
Here is my webpack config. Does anyone see what settings I have misconfigured? This is a React.js project (custom webpack config, create-react-app not used)
const webpack = require("webpack");
const dotenvWebpack = require("dotenv-webpack");
const path = require("path");
module.exports = {
entry : {
adminArea :
['./adminSettingsArea/src/index.jsx']
},
output : {
filename : 'shared/[name].bundle.js',
path : path.resolve(__dirname, ''),
publicPath : "/",
},
devtool: 'source-map',
devServer : {
contentBase : './adminSettingsArea/src',
hot : true,
historyApiFallback : true
},
plugins : [
new webpack.HotModuleReplacementPlugin(),
new dotenvWebpack()
],
module : {
rules : [
{
test : /\.(js|jsx)$/,
exclude : [/node_modules/, /vendor/],
use : {
loader : "babel-loader",
options : {
presets : [
'#babel/preset-env',
"#babel/preset-react"
]
},
}
}, {
test : /\.css$/i,
use : ['style-loader', 'css-loader'],
}
],
},
};

Specify the webpack "mainFields" on a case by case basis

Webpack has a resolve.mainFields configuration: https://webpack.js.org/configuration/resolve/#resolvemainfields
This allows control over what package.json field should be used as an entrypoint.
I have an app that pulls in dozens of different 3rd party packages. The use case is that I want to specify what field to use depending on the name of the package. Example:
For package foo use the main field in node_modules/foo/package.json
For package bar use the module field in node_modules/bar/package.json
Certain packages I'm relying on are not bundled in a correct manner, the code that the module field is pointing to does not follow these rules: https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md This causes the app to break if I wholesale change the webpack configuration to:
resolve: {
mainFields: ['module']
}
The mainFields has to be set to main to currently get the app to work. This causes it to always pull in the CommonJS version of every dependency and miss out on treeshaking. Hoping to do something like this:
resolve: {
foo: {
mainFields: ['main']
},
bar: {
mainFields: ['module'],
}
Package foo gets bundled into my app via its main field and package bar gets bundled in via its module field. I realize the benefits of treeshaking with the bar package, and I don't break the app with foo package (has a module field that is not proper module syntax).
One way to achieve this would be instead of using resolve.mainFields you can make use of resolve.plugins option and write your own custom resolver see https://stackoverflow.com/a/29859165/6455628 because by using your custom resolver you can programmatically resolve different path for different modules
I am copy pasting the Ricardo Stuven's Answer here
Yes, it's possible. To avoid ambiguity and for easier implementation,
we'll use a prefix hash symbol as marker of your convention:
require("#./components/SettingsPanel");
Then add this to your configuration file (of course, you can refactor
it later):
var webpack = require('webpack');
var path = require('path');
var MyConventionResolver = {
apply: function(resolver) {
resolver.plugin('module', function(request, callback) {
if (request.request[0] === '#') {
var req = request.request.substr(1);
var obj = {
path: request.path,
request: req + '/' + path.basename(req) + '.js',
query: request.query,
directory: request.directory
};
this.doResolve(['file'], obj, callback);
}
else {
callback();
}
});
}
};
module.exports = {
resolve: {
plugins: [
MyConventionResolver
]
}
// ...
};
resolve.mainFields not work in my case, but resolve.aliasFields works.
More details in https://stackoverflow.com/a/71555568/7534433

Slow Small Webpack 2 Build - Tree Shaking - Sass - Chunking

I've put together a very basic webpack 2 build, but it seems to be slow for the project size. The three things I wanted have were:
Chunking (js & scss)
SCSS compiling
Tree Shaking
Webpack seemed to be a good choice for being able to do these things. I've been using Gulp and Rollup, but the SCSS/Chunking along side of the tree shaking is a nice thing.
It takes around 4000 - 5000ms to compile the build, which wouldn't be the end of the world except the project is so small, so I'm worried about that becoming much larger as a project grows.
I've tried a couple things to improve the speed.
resolve : {
root: path.resolve(__dirname,'src')
}
This did help, reducing the time by a couple hundred ms, so that was great. I tried to take this further by also resolving alias, but that didn't really show any gains as far as I could tell.
I set devTool to eval as well. Beyond this I haven't really been able to improve things, but I'm sure it's something in the way I've set things up. It's worth noting that while 'webpack' compiles the build, running the webpack-dev-server doesn't. It's starts up, hangs on the compile and then crashes. This may or may not be a separate issue, but I thought it was worth including.
I'm also using ES6 System.import for chunking (just as a note).
I put the project up on git, so feel free to pull it down: https://github.com/loriensleafs/trying-out-webpack2
The webpack.config.js is:
var path = require('path'),
webpack = require('webpack'),
CleanPlugin = require('clean-webpack-plugin'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
production = process.env.NODE_ENV === 'production';
var plugins = [
new ExtractTextPlugin({ filename: 'bundle.css', allChunks: true}),
new webpack.optimize.CommonsChunkPlugin({
name : 'vendor',
children : true,
minChunks : 2
})
];
if (production) {
plugins = plugins.concat([
new CleanPlugin('builds'),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.MinChunkSizePlugin({
minChunkSize: 51200, // ~50kb
}),
new webpack.optimize.UglifyJsPlugin({
mangle: true,
compress: {
warnings: false, // Suppress uglification warnings
},
}),
new webpack.DefinePlugin({
__SERVER__ : !production,
__DEVELOPMENT__ : !production,
__DEVTOOLS__ : !production,
'process.env': {
BABEL_ENV: JSON.stringify(process.env.NODE_ENV),
}
})
]);
}
module.exports = {
// debug : !production,
devTool : production ? false : 'eval',
entry : './src',
output : {
path : 'builds',
filename : 'bundle.js',
chunkFilename : 'chunk.js',
publicPath : 'builds/'
},
resolve : {
root: path.resolve(__dirname,'src')
},
plugins : plugins,
module : {
loaders: [
{
test : /\.(png|gif|jpe?g|svg)$/i,
loader : 'url',
query : {
limit: 10000
}
},
{
test : /\.js$/,
include : /src/,
exclude : /node_modules/,
loader : 'babel'
},
{
test : /\.scss$/,
include : /src/,
exclude : /node_modules/,
loader : ExtractTextPlugin.extract(['css','sass'])
},
{
test : /\.html$/,
loader : 'html'
}
]
}
};
Thanks for any advice/help folks have on this. If there's any other helpful info I can post on here please let me know.

Uncaught Error: Module name "lib/chai" has not been loaded yet for context: use require([])

i m using karma-mocha ..my karma.conf file is working with karma-jasmine...but not working with karma-mocha....my karma.conf file:--
module.exports = function(config){
config.set({
basePath : '../app',
preprocessors: {
'**/*.html':'ng-html2js'
},
ngHtml2JsPreprocessor: {
prependPrefix: '/'
},
files : [
'node_modules/jquery/**/*.js',
'lib/angular/angular.js',
'lib/angular/angular-*.js',
'../test/lib/angular-mocks.js',
'../test/lib/sinon-1.15.0.js',
'../test/chai/chai.js',
'js/**/*.js',
'../test/unit/**/*.js',
'**/*.html'
],
autoWatch : true,
frameworks: ['mocha','requirejs','chai'],
browsers : ['Chrome'],
plugins : [
'karma-chrome-launcher',
'karma-mocha',
'karma-ng-html2js-preprocessor',
'karma-requirejs',
'karma-chai'
],
junitReporter : {
outputFile: 'test_out/unit.xml',
suite: 'unit'
}
});
};
you are missing chai lib path files array in which is dependency to mocha.include it.
files : [
'node_modules/jquery/**/*.js',
'lib/angular/angular.js',
'lib/angular/angular-*.js',
'../test/lib/angular-mocks.js',
'../test/lib/sinon-1.15.0.js',
'../test/chai/chai.js',
'js/**/*.js',
'../test/unit/**/*.js',
'**/*.html'
],
I came across a similar situation just with Jasmine.
I'd like to introduce my solution.
Try it what is written in the error message. There is a link to a website: http://requirejs.org/docs/errors.html#notloaded
//If this code is not in a define call,
//DO NOT use require('foo'), but use the async
//callback version:
require(['foo'], function (foo) {
//foo is now loaded.
});
My case written for Jasmine in Coffee script looks like this:
sinon = require(['sinon', 'jasmine-sinon']) (foo)->
Now I can use sinon as an object in my unit test and can also follow the documentation of sinon, as well as jasmin-sinon.

Using UnderscoreJS with RequireJS

I'm trying to use/load UnderscoreJS 1.7.0 with RequireJS 2.1.14-3. At my application startup, UnderscoreJS is well loaded, but it is "undefined". See details below:
main.js
define(function() {
// Configuration of RequireJS
requirejs.config({
enforceDefine : true,
map : {
'*': {
...
'underscore' : 'webjars/underscorejs/1.7.0/underscore'
},
},
// The base URL is just the top-level directory where the files are stored
baseUrl : './',
// Kick-start the application by loading these files
deps : [ 'MyPanel' ],
});
});
The module using it :
define(['ractive',
'underscore',
...],
function(Ractive,
_,
...){
var Foo = Ractive.extend({
...
oninit: function(){
var anArray = [1, 2, 3]
_.each(anArray, function(item){
...
})
}
}
And the result in the browser console :
The underscoreJS file is loaded by the browser:
This must be a detail, but I managed my Javascript dependencies with mavenand webjars
So why is my _ undefined ?
If you look at the source of Underscore 1.7.0, you see it registers itself like this:
if (typeof define === 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
}
Note the first argument to define. This hardcodes the name of the module as 'underscore'.
The problem is that you are using a map configuration which is not compatible with this hardcoded name. What you do is tell RequireJS "in all modules ("*"), when the module requires a module with the name 'underscore', then please return instead the module with the name 'webjars/underscorejs/1.7.0/underscore'". So when you require 'underscore':
RequireJS looks for the module named 'webjars/underscorejs/1.7.0/underscore' instead.
It uses the default path for such a module name and finds a file at that location. It loads the file and executes it.
However, the file contains a define calls that defines 'underscore', not 'webjars/underscorejs/1.7.0/underscore'. So RequireJS is not able to honor the request.
Instead of map, you should be using a paths configuration for Underscore. Something like:
paths : {
'underscore' : 'webjars/underscorejs/1.7.0/underscore'
}
This tells RequireJS something like "you'll find the module named 'underscore' at the location 'webjars/underscorejs/1.7.0/underscore'". When you use this, the name of the module requested and the name of the module defined match.

Resources