问题
I'm using gulp + browserify to bundle my source but i got always the same error : jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file. SignalR get $ = undefined...
I split my source into two bundle : vendor and app. Vendor bundle get lib's id from packages.json and the bundle require it. App bundle get main entry and i passe id's lib to this bundle with bundle.external.
Here my packages.json :
"browser": {
"angular-notify": "./node_modules/angular-notify/dist/angular-notify.js",
"angular-i18n": "./node_modules/angular-i18n/angular-locale_fr.js",
"jquery": "./node_modules/jquery/dist/jquery.js",
"signalR": "./node_modules/ms-signalr-client/jquery.signalr-2.2.0.js",
"moment": "./node_modules/moment/moment.js",
"moment-business": "./Scripts/Vendor/js/moment-business.js"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"browserify-shim": {
"jquery": "$",
"signalR": {
"depends": [
"jquery:jQuery"
]
},
"moment": "moment"
}
Here my gulp taks :
'use strict';
import gulp from 'gulp';
import gulpLoadPlugins from 'gulp-load-plugins';
import browserify from 'browserify';
import browserifyInc from 'browserify-incremental';
import ngHtml2Js from 'browserify-ng-html2js';
import shim from 'browserify-shim';
import xtend from 'xtend';
import tsify from 'tsify';
import babelify from 'babelify';
import minifyify from 'minifyify';
import source from 'vinyl-source-stream';
import buffer from 'vinyl-buffer';
import browserSync from 'browser-sync';
import packageJson from './package.json';
const $ = gulpLoadPlugins();
let bs = browserSync.create();
let dependenciesCss = [
'bootstrap',
'font-awesome',
'animate.css'
];
let externalDependenciesjs = [
'signalR',
'moment-business'
];
let dependenciesJs = Object.keys(packageJson.dependencies).filter(
key => (
dependenciesCss.every(
libCssName => (key.trim() !== libCssName)
)
)
);
dependenciesJs = dependenciesJs.concat(externalDependenciesjs);
/*************************************
* SCRIPTS (build) *
*************************************/
let extensions = ['.js', '.json', '.ts'];
let bundler = browserify(xtend(browserifyInc.args, {
entries: 'Scripts/App/app.ts',
debug: true,
extensions,
cache: {},
packageCache: {},
fullPaths: true
}))
.external(dependenciesJs)
.plugin(tsify, {
target: 'es6'
})
.transform(babelify.configure({
extensions,
}))
.plugin(minifyify, {
map: 'app.min.js.map',
output: 'Scripts/Dist/app.min.js.map'
});
function compile() {
bundler.on('log', $.util.log);
browserifyInc(bundler, {
cacheFile: './.tmp/browserify-cache.json'
});
$.util.log('Bundling JS ...');
return bundler.bundle()
.pipe($.plumber({
errorHandler: browserifyError
}))
.on('error', browserifyError)
.pipe(source('app.min.js'))
.pipe(buffer())
.pipe($.size({
title: 'scripts'
}))
.pipe(gulp.dest('Scripts/Dist'))
.pipe($.if(bs.active, bs.stream({
once: true
})));
}
let bundlerVendor = browserify(xtend(browserifyInc.args, {
debug: true,
extensions,
cache: {},
packageCache: {},
fullPaths: true
}))
.require(dependenciesJs)
.plugin(minifyify, {
map: 'vendor.min.js.map',
output: 'Scripts/Dist/vendor.min.js.map'
});
function compileVendor() {
bundlerVendor.on('log', $.util.log);
browserifyInc(bundlerVendor, {
cacheFile: './.tmp/browserify-vendor-cache.json'
});
$.util.log('Bundling vendor JS ...');
return bundlerVendor.bundle()
.pipe($.plumber({
errorHandler: browserifyError
}))
.on('error', browserifyError)
.pipe(source('vendor.min.js'))
.pipe(buffer())
.pipe($.size({
title: 'scripts vendor'
}))
.pipe(gulp.dest('Scripts/Dist'))
.pipe($.if(bs.active, bs.stream({
once: true
})));
}
function browserifyError(err) {
error(err);
this.end();
}
Vendor bundle haven't entry point, it only require lib. Here my app bundle entry :
/// <reference path="_references.ts" />
import 'signalR';
import 'moment';
import 'moment-business';
import 'moment-range';
import 'angular';
import 'angular-messages';
import 'angular-mocks';
import 'angular-animate';
import 'angular-file-upload';
import 'angular-notify';
import 'angular-i18n';
import 'angular-ui-bootstrap';
import 'angular-ui-router';
import 'angular-vs-repeat';
import 'postal';
import Route from './route';
import * as Configuration from './config';
import register from './registerModule';
import {camelize} from './tools';
let modules: Array<string> = [
appName + '.Controllers',
appName + '.Directives',
appName + '.Filters',
appName + '.Services',
appName + '.Factory',
appName + '.Constant'];
modules.forEach((moduleName: string): ng.IModule => angular.module(moduleName, []));
register();
modules.push('templates');
modules.push('ui.router');
modules.push('ui.bootstrap');
modules.push('angularFileUpload');
modules.push('ngAnimate');
modules.push('ngMessages');
modules.push('cgNotify');
modules.push('vs-repeat');
angular.module(appName, modules);
angular.module(appName)
.config(
['$stateProvider', '$urlRouterProvider', '$locationProvider',
($stateProvider: ng.ui.IStateProvider,
$urlRouterProvider: ng.ui.IUrlRouterProvider,
$locationProvider: ng.ILocationProvider): Route => (
new Route($stateProvider, $urlRouterProvider, $locationProvider)
)
]);
angular.module(appName)
.config(['$logProvider', ($logProvider: ng.ILogProvider): void => {
$logProvider.debugEnabled(Configuration.ENABLED_CONSOLE_DEBUG);
}
]);
angular.module(appName)
.config(
['$provide', ($provide: ng.auto.IProvideService): void => {
/* tslint:disable:no-any */
$provide.decorator('$exceptionHandler', ['$delegate', '$window', ($delegate: Function, $window: ng.IWindowService): any => {
return (exception: any, cause: string): any => {
/* tslint:enable:no-any */
// utilisation du service $delegate pour formatter le message à afficher dans la console
$delegate(exception, cause);
};
}]);
}
]);
angular.module(appName)
.config(
['$provide', '$httpProvider', ($provide: ng.auto.IProvideService, $httpProvider: ng.IHttpProvider): void => {
$provide.factory('customHttpInterceptor', ['$q', ($q: ng.IQService) => {
return {
/* tslint:disable:no-any */
'response': (response: any): any=> (camelize(response))
/* tslint:enable:no-any */
};
}]);
$httpProvider.interceptors.push('customHttpInterceptor');
}]);
angular.module(appName).run(runAngular);
runAngular.$inject = ['$rootScope', '$location', '$log'];
function runAngular($rootScope: ng.IRootScopeService,
$location: ng.ILocationService,
$log: ng.ILogService): void {
'use strict';
$log.debug('Démarrage de l\'application : ', appName);
}
I already try to use browserify-shim transform with option global but this not work too.
回答1:
You still have to import jQuery into your code. The depends
section of browserify-shim just tells it that jQuery comes before SignalR in the bundle. It doesn't say that any time you import SignalR that it will automatically import jQuery first.
The exact solution depends on whether SignalR is expecting jQuery to simply be present in the bundle, whether it expects jQuery to be present on the window
object, or whether SignalR is a jQuery plugin that could potentially need attaching manually to the $
object.
The first solution I'd try is to simply import jQuery before you import SignalR:
/// <reference path="_references.ts" />
import $ from 'jquery';
import 'signalR';
// Rest of app.js........
来源:https://stackoverflow.com/questions/34794595/browserify-shim-on-jquery-and-signalr-not-working