requirejs no longer loads cdn scripts after optimization - requirejs

I'm struggling to get requirejs to work after optimizing with r.js
It works fine pre optimization
I'm following the docs for configuring main.js and the build profile using empty:
However after optimization, CDN scripts are no longer loaded.
public/index.html
<script data-main="editor/js/main" src="editor/js/vendor/require.js"></script>
public/editor/js/main.js
requirejs.config({
baseUrl: "/editor/js",
paths: {
"jquery": "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min",
"order": "vendor/require_order",
"underscore": "vendor/underscore",
"handlebars": "vendor/handlebars-1.0.0.beta.4",
"jquery.mobile.router": "vendor/jquery.mobile.router",
"jquery.mobile": "http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min"
}
});
require(["order!jquery", "order!underscore", "order!handlebars", "order!jam", "order!jquery.mobile"], function () {
//loaded
});
config/build.js
({
baseUrl: "../public/editor/js",
name: "main",
out: "../public/editor/js/main-built.js",
paths: {
"order": "vendor/require_order",
"underscore": "vendor/underscore",
"handlebars": "vendor/handlebars-1.0.0.beta.4",
"jquery.mobile.router": "vendor/jquery.mobile.router",
"jquery": "empty:",
"jquery.mobile": "empty:"
}
})
When I run r.js node config/r.js -o config/build.js
main-built.js is built successfully.

Is there a particular reason why you are loading everything using the order plugin?
Were you having load order problems in your built javascript?
If you load jQuery mobile normally (without the plugin) your "empty" configuration should take effect.
require(["jquery", "underscore", "handlebars", "jam", "jquery.mobile"], function () {
http://requirejs.org/docs/optimization.html#empty
You will also need to define the dependency chain for jQuery.mobile.router
requirejs.config({
paths: {
"jquery": "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min",
"order": "vendor/require_order",
"underscore": "vendor/underscore",
"handlebars": "vendor/handlebars-1.0.0.beta.4",
"jquery.mobile.router": "vendor/jquery.mobile.router",
"jquery.mobile": "http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min"
},
shim: {
"router": {
"deps" : ["jquery.mobile"]
},
"jquery.mobile" : {
"deps" : [ "jquery.mobile.router"],
"exports": "$.mobile"
},
"jquery.mobile.router": {
"exports": "$.mobile.Router"
}
}
});
see the answer to this question:
Require.js with jQueryMobile-Router
I hope that resolves your issues with requirejs, I've found it to be a very powerful and useful tool, once you get used to its structure.
_Pez

Related

Jest and Babel transpilation - SyntaxError: Cannot use import statement outside a module

I struggle to use JEST for some cases where running the tests I get
Test suite failed to run
...node_modules\p-retry\index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import retry from 'retry';
^^^^^^
SyntaxError: Cannot use import statement outside a module
> 1 | import pRetry from 'p-retry';
| ^
2 |
3 | export function Retry(tries: number) {
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
at Object.<anonymous> (src/common/Retry.ts:1:1)
Meanwhile my webpack build works nice with typescript and babel. I tried a lot of stuff (see below to get it working but no success so far - and haven't really been able to understand whats going on. From my pov - though the transpilation stuff is kind of a black area so far for me I tried to enable Jest to use ESModules andprovide code as such as well as tried providing commonJS module code.
So I am looking for alternative options and ways to investigate further. Particularly one thing strikes me as strange:
the Retry.ts file from the error is one of my files which imports the pRetry (a node_module written in ESModule style) which in its code does the import retry from 'retry' (another node-module written in commonJS style)from the very first line of the error.
So what seems to happen to me is that the pRetry is not transformed from it's ESModule Code (the source of pRetry starts with import retry from 'retry';) and just wrapped in some commonJS code instead if I interpret the syntax correctly.
So my next steps would likely be investigate what babel-jest really generates and check what's up there and try to deduct furhter. Does anybody know how to achieve this (especially understand what babel-jest generates) or has another idea?
Things I tried - all failed (sometimes slightly different errors)
using plugins: ["#babel/plugin-transform-runtime"] in babel.config.js
changing target and module in tsconfig.json to es5
introducing below in jest.config.ts transformIgnorePatterns: ["node_modules/?!(p-retry)"]
using the following in jest.config.ts
preset: "ts-jest",
transform: {
'^.+\.(ts|tsx)?$': 'ts-jest',
"^.+\.(js|jsx)$": "babel-jest"}
or alternatively with ts-jest for both or babel-jest for both
migrating from .babelrc file to babel.config.js as suggested by one post
AllowJS : true in tscfonfig.json and transformIgnorePatterns in jest in combination
adding ["#babel/plugin-transform-runtime",{"regenerator": true}] to babel.config
Using
preset: "ts-jest",
testEnvironment: "node",
transform: {"node_modules/p-retry/.+\.(j|t)sx?$": "ts-jest"},
transformIgnorePatterns: ["node_modules/(?!p-retry/.*)"]
in jest.config
using "transform-es2015-modules-commonjs" in babel.config
using #babel/plugin-transform-modules-commonjs in babel.config
Applying the following steps as suggest by https://stackoverflow.com/questions/35756479/does-jest-support-es6-import-export#:~:text=Jest%20will%20enable%20compilation%20from,json%20.&text=If%20you%20don't%20want%20to%20pollute%20your%20project%20with%20
Make sure you don't transform away import statements by setting
transform: {} in config file
Run node#^12.16.0 || >=13.2.0 with --experimental-vm-modules flag
Run your test with jest-environment-node or jest-environment-jsdom-sixteen.
playing with testenvironment like jest-environment-node, node or jsdom in jest.config.ts
jest-config.ts:
const tsconfig = require("./tsconfig.json");
const moduleNameMapper = require("tsconfig-paths-jest")(tsconfig)
export default {
collectCoverage: true,
coverageDirectory: "analysis/coverage",
coveragePathIgnorePatterns: ["/node_modules/"],
collectCoverageFrom: ["src/**/*.{js,jsx,ts}"],
coverageReporters: ["json", "lcov", "text", "clover"],
coverageThreshold: {
global: {
branches: 0,
functions: 0,
lines: 0,
statements: 0
},
},
clearMocks: true,
coverageProvider: "babel",
moduleNameMapper,
roots: ["<rootDir>/src/", "<rootDir>/test/"],
testEnvironment: 'jest-environment-node',
testPathIgnorePatterns: [
"\\\\node_modules\\\\"
],
"transform": {
"^.+\\.(js|ts|jsx)$": "babel-jest"
}
};
babel.config.js:
module.exports = {
presets: ['#babel/preset-typescript',
['#babel/preset-env', {
targets: { node: "current" }
}],
'#babel/preset-flow',
],
plugins: [["#babel/plugin-transform-modules-commonjs"], ["#babel/plugin-proposal-decorators", { "legacy": true }], ["#babel/plugin-proposal-class-properties"]]
}
Extract from package.json
"#babel/core": "^7.16.12",
"#babel/plugin-proposal-decorators": "^7.16.5",
"#babel/plugin-transform-modules-commonjs": "^7.16.8",
"#babel/plugin-transform-runtime": "^7.16.10",
"#babel/preset-env": "^7.14.4",
"#babel/preset-flow": "^7.16.7",
"#babel/preset-typescript": "^7.13.0",
"#babel/runtime": "^7.16.7",
"babel-jest": "^27.4.6",
"babel-plugin-transform-regenerator": "^6.26.0",
"jest": "^27.0.4",
"jest-config": "^27.4.5",
"jest-esm-transformer": "^1.0.0",
"ts-jest": "^27.1.3",
"tsconfig-paths-jest": "^0.0.1",
"core-js": "^3.20.0",
Turns out I was close.
With a change of babel.config.ts by adding esmodules: false it is done :-)
module.exports = {
presets: ['#babel/preset-typescript',
['#babel/preset-env', {
targets: { esmodules: false, node: "current" }
}],
'#babel/preset-flow',
],
plugins: [["#babel/plugin-transform-modules-commonjs"], ["#babel/plugin-proposal-decorators", { "legacy": true }], ["#babel/plugin-proposal-class-properties"]]
}
My solution with "jest": "^28.1.0":
In package.json
under devDependencies add:
"#babel/preset-env": "^7.18.10"
and,
"jest": {
"transform": {
"^.+\\.[t|j]sx?$": "babel-jest"
}
},
In babel.config.json add:
{
"presets": ["#babel/preset-env"]
}
You can let Jest do not ignore transforming p-retry by adding this in your jest. config.js, it works for me.
"transformIgnorePatterns": [
"node_modules/(?!(p-retry)/)",
],
In my case I had to add specific module mappings as detailed here: https://stackoverflow.com/a/65250052/285549
This forces Jest to load the CommonJS version of the module since the tests are running in Node even though the eventual target is the browser.

Using bootbox in RequireJS app

I have a sample app.js file with:
requirejs.config({
"baseUrl": "js/lib",
"paths": {
"jquery": "jquery",
"app": "../app",
"bootstrap": "bootstrap/js/bootstrap.bundle",
"bootbox": "bootbox.min"
},
"shim": {
"bootstrap": {
"deps": ["jquery"],
"exports": 'bootbox'
},
"main": { "deps": ["jquery","bootstrap"] },
"bootbox": {
"deps": ["jquery","bootstrap"],
"exports": 'bootbox'
},
}
});
require(['jquery','bootstrap','bootbox'], function($){
$(function(jquery) {
bootbox.alert("bla")
});
});
When I run my page, I can see the correct JS files being grabbed:
...yet my code fails:
bootbox.alert("bla")
Gives:
ReferenceError: bootbox is not defined
I must be missing something simple (again, apologies if this is a newbie error - I'm still trying to get my head around this library)
Don't use shim with Bootbox. If you look at the source code of Bootbox, you'll see it calls define, which registers it as a proper AMD module. The shim option is only for code which is not a proper AMD module.
Now, the define in Bootbox does this:
define(["jquery"], factory);
It sets a dependency on jQuery, but that is wrong, because in fact Bootbox also depends on Bootstrap being present. So we need to fix this. The following shows how you can fix it. You can use a map configuration option so that when Bootbox requires jQuery, it gets Bootstrap. And you set a shim for Bootstrap so that, in addition to having a dependency on jQuery, its module value is the same as jQuery ($).
Without the map setup, there's no guarantee that Bootstrap will load before Bootbox and you'll be facing a race condition: sometimes it'll work, sometimes not.
requirejs.config({
baseUrl: ".",
paths: {
jquery: "//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min",
bootstrap: "//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min",
bootbox: "//github.com/makeusabrew/bootbox/releases/download/v4.4.0/bootbox.min"
},
shim: {
"bootstrap": {
"deps": ["jquery"],
// We set bootstrap up so that when we require it, the value with get is just $.
// This enables the map below.
"exports": "$"
},
},
map: {
// When bootbox requires jquery, give it bootstrap instead. This makes it so that
// bootstrap is **necessarily** loaded before bootbox.
bootbox: {
jquery: "bootstrap",
},
}
});
require(["jquery", "bootbox"], function($, bootbox) {
$(function(jquery) {
bootbox.alert("bla");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />

Loading hyperagent with require.js

I've used bower to install hyperagent, and it pulled down some dependencies, I'm just not sure how to properly initialise it now.
As far as I call tell, it doesn't support AMD loading, so I'm trying to use a shim config. I've tried a few things, looking something like this:
<script src="{{ path('root') }}bower/requirejs/require.js"></script>
<script>
require.config({
"baseUrl": "{{ url('root') }}/bower/",
paths: {
"vue": 'vue/dist/vue.min',
"hyperagent": 'hyperagent/dist/hyperagent',
"jquery": "jquery/jquery.min",
"uri": "uri.js/src/URI.min"
},
shim: {
'hyperagent': {
'deps': ['jquery', 'uri'],
'exports': 'Hyperagent'
}
}
});
</script>
When I later do
require(['vue', 'hyperagent'], function(Vue, Hyperagent) { ... });
Hyperagent is undefined.
Am I way off the mark? (Oh, and the mustaches are twig, this is a Symfony project)
Thanks to Ben Weiner for this one. Taken from here.
I installed hyperagent and URIjs via bower and for now I'm just setting window.URI as a global before requiring hyperagent. Here's the relevant part of my require.js config:
require.config({
paths: {
'hyperagent': '../bower_components/hyperagent/dist/amd/hyperagent',
'URIjs': '../bower_components/uri.js/src',
}
});
To use it I just define an amd module that returns a configured hyperagent eg configured_hyperagent.js:
define(function(require) {
window.URI = require('URIjs/URI');
window.URITemplate = require('URIjs/URITemplate');
Hyperagent = require('hyperagent');
// Hyperagent.configure() etc..
return Hyperagent;
});

grunt bowercopy task not found

I can't figure out my configuration problem. When I try to run 'grunt bowercopy', I get this error message:
Warning: Task "bowercopy" not found. Use --force to continue.
If I run 'grunt jshint', jshint works fine.
Here is my package.json:
{
"name": "treblebull",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "~3.2.6",
"jade": "~0.31.2",
"underscore": "~1.5.2",
"pg": "~2.11.1"
},
"devDependencies": {
"grunt": "~0.4.2",
"grunt-bowercopy": "~0.7.1",
"grunt-contrib-jshint": "~0.8.0",
"load-grunt-tasks": "~0.2.1"
}
}
and here is my gruntfile:
'use strict';
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
options: {
jshintrc: '.jshintrc'
},
gruntfile: {
src: 'Gruntfile.js'
},
lib: {
src: ['lib/**/*.js']
},
test: {
src: ['test/**/*.js']
}
},
bowercopy: {
options: {
clean: true
//srcPrefix: 'bower_components'
},
libs: {
options: {
// destPrefix: 'public/js/lib'
},
files: {
'angular.js': 'angular/angular.js'
//'underscore.js': 'underscore/underscore.js',
//'underscore.string.js': 'underscore.string/underscore.string.js'
}
}
}
});
grunt.loadNpmTasks('grunt-bowercopy');
grunt.loadNpmTasks('grunt-contrib-jshint');
};
Run bower init to give yourself a bower.json file for the bowercopy task to read. Also if you already have installed everything via bower, set runBower to false in your options hash.
If you're ever having Grunt failures, it's worth running with the --v (verbose) flag to see exactly what it's failing on. Running this myself I saw it looking for a bower.json, and once I supplied one the task succeeded.
You're missing task registration, You need to register a task that you want to explicity run in grunt, so you need this
grunt.registerTask('bowercopy', ['bowercopy']);
Then you can run
grunt bowercopy
Since I can't comment on #dcodesmith's answer due to points, I have to leave an answer. I ran into the problem in that actually adding grunt.registerTask('bowercopy', ['bowercopy']);
called bowercopy's task, but it doesn't actually work. Removing it actually allowed bowercopy to copy files.

require cdn libraries in browserify without bundling it in the final js file

If I have a library that is being pulled down from cdn and wouldn't like it to be part of the final js file but be able to require it using browserify, how would I solve it?
Here is how I currently solve it using alias and a shim file.
browserify: {
options: {
debug: true,
transform: [ 'reactify' ],
alias: [
'client/shims/jquery.js:jquery'
]
},
app: {
src: 'client/app.js',
dest: 'public/app.js'
}
}
here is the shim file client/shims/jquery.js which I alias to jquery so I can use require('jquery') instead of the full path.
module.exports = $;
Is there a shortcut in grunt-browserify to support this scenario? I would like to know if it is possible to define it in Gruntfile.js without creating the shim file.
Adding external: [ 'jquery' ] seems to totally ignore it and doesn't work.
With browserify-shim you can add this in your package.json file:
"browserify": {
"transform": [
"browserify-shim"
]
},
"browserify-shim": {
"jquery": "global:$"
}
Then jquery will be available in your modules via require('jquery')
If you load jQuery before the Browserify bundle on the page, $ will be available as a global.

Resources