I've set up an app with react using react-router for routing and are having issues bundling it all.
I'm trying to build/bundle all the js files using gulp-requirejs. But somehow the shim is not included, or the react-router is just ignored. Whatever the problem is, I just end up with an error in the browser console saying Uncaught Error: app missing react-router
I'm including the most important code, feel free to ask if something doesn't make sense.
gulpfile.js
Almond.js is there to replace requirejs
var gulp = require('gulp'),
uglify = require('gulp-uglify'),
rjs = require('gulp-requirejs'),
gulp.task('requirejsBuild', function() {
rjs({
baseUrl: './app/resources/js/',
out: 'app.min.js',
paths: {
'react': '../bower_components/react/react-with-addons',
'react-router': '../bower_components/react-router/dist/react-router',
'react-shim': 'react-shim',
'jquery': '../bower_components/jquery/dist/jquery'
},
shim: {
'react-shim': {
exports: 'React'
},
'react-router': {
deps: ['react-shim']
}
},
deps: ['jquery', 'react-router'],
include: ['init'],
name: '../bower_components/almond/almond'
})
.pipe(uglify()).pipe(gulp.dest('./app/resources/js/'));
});
init.js
require.config({
baseUrl: '/resources/js/',
deps: ['jquery'],
paths: {
'react': '../bower_components/react/react-with-addons',
'react-router': '../bower_components/react-router/dist/react-router',
'react-shim': 'react-shim',
'jquery': '../bower_components/jquery/dist/jquery'
},
shim: {
'react-shim': {
exports: 'React'
},
'react-router': {
deps: ['react-shim']
}
}
});
require(['react', 'app'], function(React, App) {
var app = new App();
app.init();
});
app.js
define([
'react',
'react-router',
], function(
React,
Router,
){
var Route = Router.Route;
var RouteHandler = Router.RouteHandler;
var DefaultRoute = Router.DefaultRoute;
/**
* Wrapper for it all
*
* #type {*|Function}
*/
var Wrapper = React.createClass({displayName: "Wrapper",
mixins: [Router.State],
render: function() {
return (
React.createElement(RouteHandler, null)
);
}
});
var routes = (
React.createElement(Route, {handler: Wrapper, path: "/"}, null)
);
var App = function(){};
App.prototype.init = function () {
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(React.createElement(Handler, null), document.getElementById('content'));
});
};
return App;
}
);
index.html
Mainly containing a script tag
After build you have to manually swap the src with app.min.js
<script data-main="/resources/js/init" src="/resources/bower_components/requirejs/require.js"></script>
Related
The generated AMD file is not including required files inside anonymous function and pollute the global namespace
I got Uncaught ReferenceError: define is not defined
The generated js file https://dadasay.com/plugin/v1/js/dadasay.min.js is not including required files require.js
The js file generated by runninggulp minify_plugin_js
However, the expected export js file should be like this https://gist.github.com/anonymous/32894a4065ce338fb0416f4eb2b884dd
How could I do that in Gulp js and require.js
require.js config
'use strict';
var vendor_paths = {
require: './vendor/require',
jquery: './vendor/js/jquery-2.1.1.min',
...
}
require.config({
paths: vendor_paths,
hbs: { // optional
helpers: true, // default: true
templateExtension: 'hbs', // default: 'hbs'
partialsUrl: '' // default: ''
},
shim: {
handlebars: {
exports: 'Handlebars'
},
backbone: {
deps: [
'jquery',
'underscore'
],
exports: 'Backbone'
},
underscore: {
exports: '_'
}
},
});
require(["app"],function(App){
define(["app"], function (App) {
$("#dadasay_comments_plugin").hide();
$('head').append('<link rel="stylesheet" href='+cfg.css_style_link+' type="text/css" />');
return App.initialize();
});
});
Gulp config
var v1_assets = {
css: ['public/plugin/v1/css/*.css'],
js: ['public/plugin/v1/src/**/*.js'],
require_manifest_file: "public/plugin/v1/src/main.js"
}
gulp.task('minify_plugin_js',function(){
gulp.src(v1_assets.js)
.pipe(amdOptimize("main",{
configFile: v1_assets.require_manifest_file,
findNestedDependencies: true,
include: true
}))
.pipe(concatFile('dadasay.min.js'))
})
Exported js min file
https://dadasay.com/plugin/v1/js/dadasay.min.js
define('app_config', [], function () {
return {
server_host: SERVER_HOST,
hideCommentsThreshouldNumber: 3,
comments_req_prefix: SERVER_HOST + '/api/v1/comments/load?og_url=',
css_style_link: [
SERVER_HOST,
PLUGIN_LOCATION,
'style.min.css'
].join('/')
};
});
....
The line:
define(["app"], function (App) {
is unnecessary. You required your application asynchronously already.
I believe that you could try to use the requirejs optimizer directly within gulp instead, here's how my build task looks like:
"use strict";
const requirejs = require("requirejs");
const path = require("path");
const _ = require("underscore");
module.exports = function (options, callback) {
// RequireJS Optimizer Build Configuration
// See this: https://github.com/jrburke/r.js/blob/master/build/example.build.js
// as an example file that details all of the allowed optimizer configuration options.
var buildConfig = {
appDir: options.dest,
baseUrl: "./",
optimize: "uglify2",
optimizeCss: "standard",
findNestedDependencies: true,
dir: options.build,
removeCombined: true,
fileExclusionRegExp: options.exclude || /test/,
modules: options.modules || [{
name: "runner"
}],
allowSourceOverwrites: true
};
var config = path.join(__dirname + "/../../", options.config);
var requireConfig = require(config);
_.extend(buildConfig, requireConfig);
requirejs.optimize(buildConfig, function (text) {
callback(null, text);
}, callback);
};
And then later in gulp:
const gulp = require("gulp");
const build = require("../task/build.task");
gulp.task("build", function (callback) {
build({ some: "options" }, callback);
});
I'm new to Marionette and I just can't get routes to work.
I'm using Marionette's 2.4.1 version, and trying to do it the simplest way possible so it'll just work.
This code works for old version of Marionette, v1.0.2, which was included in one of the yeoman's generator. I know there's a huge gap between those two versoins but for every post, blog, official documentation and even books written for this framework code stays the same.
There are no errors in console, but the 'home' method just won't start.
Am I missing something here?
application.js (Application body):
define(['backbone', 'marionette'],
function (Backbone, Marionette) {
'use strict';
var App = new Marionette.Application();
App.Router = Marionette.AppRouter.extend({
appRoutes: {
"home": "home"
}
});
var myController = {
"home": function() {
console.log("This thing just won't work.");
}
};
/* Add initializers here */
App.addInitializer(function () {
console.log('App initialized');
new App.Router({
controller: myController
});
});
App.on("initialize:after", function () {
if (Backbone.history) {
Backbone.history.start();
}
});
return App;
});
main.js (Starts our app defined in application.js):
require(['marionette', 'application'],
function ( Marionette, App ) {
'use strict';
App.start();
});
config.js (Config for require.js)
require.config({
baseUrl: "/scripts",
/* starting point for application */
deps: ['marionette', 'main'],
shim: {
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
},
marionette: {
deps: ['backbone'],
exports: 'Marionette'
}
},
paths: {
backbone: '../bower_components/backbone/backbone',
jquery: '../bower_components/jquery/dist/jquery',
underscore: '../bower_components/underscore/underscore',
/* alias all marionette libs */
'marionette': '../bower_components/marionette/lib/core/backbone.marionette',
'backbone.wreqr': '../bower_components/backbone.wreqr/lib/backbone.wreqr',
'backbone.babysitter': '../bower_components/backbone.babysitter/lib/backbone.babysitter'
}
});
It looks like you're missing a reference to the router's controller.
Try updating the Router to include a reference to myController:
App.Router = Marionette.AppRouter.extend({
controller: myController,
appRoutes: {
"home": "home"
}
});
See AppRouter docs for more infomation:
http://marionettejs.com/docs/v2.4.1/marionette.approuter.html
It seems that initialize:after in:
App.on("initialize:after", function () {
if (Backbone.history) {
Backbone.history.start();
}
});
isn't supported in newest versions of Marionette and I was supposed start instead:
App.on("start", function () {
if (Backbone.history) {
Backbone.history.start();
}
});
Most posts about Marionette seems to be rather outdated. Those are still really helpful but be sure to verify it with the official framework's documentation.
I should've done that in the first place..
I have this code:
define(['plugins/dialog', 'knockout', 'backend', 'durandal/app', 'datepicker', 'datepicker_ko'], function (dialog, ko, backend, app, datepicker, datepicker_ko) {
var ApplicationForm = function(config) {
this.config = ko.observableArray(config);
};
ApplicationForm.prototype.submit = function() {
backend.setFormConfig(this.config()).then(function(response){
dialog.close(this);
});
};
ApplicationForm.show = function(config){
return dialog.show(new ApplicationForm(config));
};
return ApplicationForm;
});
congig in the mainfile main.js:
requirejs.config({
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-3.1.0',
'validation_ko': '../lib/knockout/knockout-validation',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1',
'underscore': '../lib/underscore/underscore-min',
'datepicker': '../lib/datepicker/bootstrap-datepicker',
'datepicker_ko': '../lib/datepicker/datepicker_ko'
},
shim: {
'bootstrap': {
deps: ['jquery'],
exports: 'jQuery'
}
}
});
And my Problem is, that I get the error:
TypeError: this.config is not a function
I do this many times in my project ans with observables works it fine but not with observableArrays. What do I wrong?
define(['plugins/dialog',
'knockout',
'backend',
'durandal/app',
'datepicker',
'datepicker_ko'], function (dialog, ko, backend, app, datepicker, datepicker_ko) {
var config = ko.observableArray([]);
var submit = function(){
var request = config();
backend.setFormConfig(request).then(function(response){
dialog.close(viewmodel);
});
}
var show = function(config){
dialog.show(viewmodel, config);
}
var activate = function(config){
config(config);
}
var viewmodel =
{
config: config,
submit: submit,
show: show,
activate: activate
};
return viewmodel;});
Is there any way to do something like following
shim: {
bsAlert || bsTooltip || dbDropdown: {
deps: ['jquery']
}
}
instead of following
shim: {
bsAlert: {
deps: ['jquery']
},
bsTooltip: {
deps: ['jquery']
},
bsDropdown: {
deps: ['jquery']
}
}
My shim list is getting too long; Is there any way, where i can use logical operator or regular expressions to optimize my shim configuration?
You probably already knew this but using || for this purpose won't work in plain JavaScript. I do not know of a JavaScript "extension" language (like CoffeeScript) which will allow what you propose.
However, the configuration object you pass to requirejs can be dynamically constructed. So you could do something like:
var config = {
baseURL: "lib",
paths: { ... },
shim: {
moduleA: { ... }
}
};
var s = config.shim;
s.bsAlert = s.bsTooltip = s.bsDropdown = { deps: ['jquery'] };
require.config(config);
If you are going to need to do this a lot, it would be possible to write a config like:
var config = {
baseURL: "lib",
paths: { ... },
shim: {
moduleA: { ... }
"bsAlert || bsTooltip || bsDropdown": { deps: ['jquery'] },
}
};
And then have a function walk over the config object to convert keys of the form "A || B" into what requirejs wants before passing the object to requirejs. And since requirejs combines configurations when you configure it multiple times, you could have something like:
require.config({
// ... minimal config allowing to find "convert_config"
});
var convert_config = require("convert_config"); // module returns function
var config = {
baseURL: "lib",
paths: { ... },
shim: {
moduleA: { ... },
"bsAlert || bsTooltip || bsDropdown": { deps: ['jquery'] },
}
};
convert_config(config); // modifies object in-place
require.config(config); // pass the full configuration to requirejs
Adding to #Louis-Dominique Dubeau answer. Definition for convert config can be given as follows.
define("convert_config", function(){
function convert_config(config){
for(var index in config.shim){
if(index.indexOf("||")!=-1){
var keys = index.split("||");
for(var i=0; i<keys.length; i++){
config.shim[keys[i]] = config.shim[index];
}
delete config.shim[index]
}
}
return config;
}
return convert_config;
})
var convert_config = require("convert_config");
var config = {
baseURL: "lib",
paths: {},
shim: {
moduleA: {},
"bsAlert || bsTooltip || bsDropdown": { deps: ['jquery'] },
}
};
config = convert_config(config);
require.config(config);
I am trying to convert an existing Backbone.js project into Require.js.
As recommended I am modularising my components. My router is the starting point in the application, thus my main.js require file looks like this:
requirejs.config({
'baseUrl': '/',
'paths': {
'app': 'app',
// define vendor paths
'jquery' : 'bower_components/jquery/jquery',
'underscore' : 'bower_components/underscore/underscore',
'backbone' : 'bower_components/backbone/backbone',
'handlebars' : 'bower_components/handlebars/handlebars',
'nprogress' : 'bower_components/nprogress/nprogress',
},
'shim':{
'jquery': {
'exports': '$'
},
'underscore': {
'exports': '_'
},
'backbone': {
'deps': ['jquery', 'underscore'],
'exports': 'Backbone'
},
'handlebars': {
'exports': 'Handlebars'
}
}
});
require(['app/js/routes/router'], function(Router) {
// Fire up the quattro
});
My router then looks like this
define(['backbone', '/app/js/views/HomepageView'], function(Backbone) {
var AppRouter = Backbone.Router.extend({
routes: {
"": "showHomepage",
"categories/:sofa": "showCategoryList",
"range/:categoryName/:sofaName": "showProductRange",
"customersearch/:customerName": "showCustomerSearch"
}
});
// Initialise our router
var router = new AppRouter;
router.on("route:showHomepage", function(param){
localStorage.removeItem('lastProduct');
var homepageview = new HomepageView({ el: $('#content') });
})
// Start the router
Backbone.history.start();
});
However when I navigate to my route '/' for HomepageView to initialise, I get the following error no matter what I try and I cannot seem to find the solution..
Uncaught ReferenceError: Backbone is not defined HomepageView.js:1
changing the first line to the following would be a start.
define(['backbone', '/app/js/views/HomepageView'], function(Backbone, HomePageView) {