8

I want to include jQuery and SignalR in my Angular2-Application and wire everything up with webpack.

I therefore installed jQuery via npm.

package.json

"dependencies": {
    // ...
    "jquery": "2.1.4",
    // ...
  },

Files and folders are installed correctly.

I now target these files in my vendor.ts to get webpack to find and include them:

import 'jquery';
import 'bootstrap/dist/js/bootstrap.js';
import '../../bower_components/signalr/jquery.signalR';

And webpack gets these files and wires them up. I can see this in my vendor.js. jQuery is present there. Also the jquery signalR-File.

My webpack.config:

var webpack = require("webpack");
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: {
        "vendor": "./wwwroot/app/vendor",
        "polyfills": "./wwwroot/app/polyfills",
        "app": "./wwwroot/app/boot"
    },
    output: {
        path: __dirname,
        filename: "[name]-[hash:8].bundle.js"
    },
    resolve: {
        extensions: ['', '.ts', '.js', '.html']
    },
    devtool: 'source-map',
    module: {
        loaders: [
            {
                test: /\.ts/,
                loaders: ['ts-loader'],
                exclude: /node_modules/
            },
            {
                test: /\.html$/,
                loader: 'html'
            },
            {
                test: /\.css$/,
                loader: 'raw'
            }
        ]
    },
    plugins: [
         new webpack.ProvidePlugin({
            jQuery: 'jquery',
            $: 'jquery',
            jquery: 'jquery'
        }),
        //new webpack.optimize.DedupePlugin(),
        new webpack.optimize.CommonsChunkPlugin({
            name: ["app", "vendor", "polyfills"]
        })
    ]
}

Loaded in my index like:

<script src="js/polyfills-2eba52f6.bundle.js"></script>
<script src="js/vendor-2eba52f6.bundle.js"></script>
<script src="js/app-2eba52f6.bundle.js"></script>

But when I try to use it in my angular2 component like:

// ...

declare var jQuery:any;
declare var $:any;

@Injectable()
export class MySignalRService {

    private connection;

    constructor() {

        this.connection = $.hubConnection(CONFIGURATION.baseUrls.server + 'signalr/');
        jQuery.hubConnection(CONFIGURATION.baseUrls.server + 'signalr/');

        // ...
    }

    //...

I alway get the message that

$.hubConnection is not a function

Error: jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file.

consoling out "$" and "jquery" is undefined.

What can I do to access the singalr-Function in webpack?

BR Tenoda

Tenoda
  • 193
  • 2
  • 14
  • Have you tried this http://stackoverflow.com/questions/29080148/expose-jquery-to-real-window-object-with-webpack? – yurzui Sep 10 '16 at 10:20
  • No, not yet. But i'll try that. Thank you. If I include jQuery explicitly in index.html everything works as expected... But I will try the proposed solution... – Tenoda Sep 10 '16 at 10:29
  • Okay, that did not work either. Added ` { test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" },` to my webpack.config which did not do it. THen I trief to add `import "jQuery"` in my vendor.ts which also did not work... – Tenoda Sep 10 '16 at 11:11
  • Can you share your project or a minimal copy on github? – yurzui Sep 10 '16 at 11:14
  • It is a copy of this branch here https://github.com/FabianGosebrink/ASPNET-Core-Angular2-SignalR-Typescript/tree/AspNetCore1.0 – Tenoda Sep 10 '16 at 11:23
  • I got jquery to work but still got "$.hubConnection is not a function"...also when i include the signalr-file... – Tenoda Sep 10 '16 at 12:29
  • Try this option `window.jQuery = require("jquery");` It works for me http://take.ms/cwBek See also http://take.ms/bhZKD – yurzui Sep 10 '16 at 12:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/123056/discussion-between-tenoda-and-yurzui). – Tenoda Sep 10 '16 at 12:49
  • I am having this same issue. What was the final solution? – Ben Cameron Nov 03 '16 at 15:37
  • Tip: The title of the question should better be 'Include jQuery-Signalr in Angular2 with webpack' – hannes neukermans Nov 07 '16 at 07:35

3 Answers3

8

Clean solution: use expose-loader !!

npm install expose-loader --save-dev

inside your vendor.ts

> import 'expose?jQuery!jquery';
> import '../node_modules/signalr/jquery.signalR.js';

inside your webpack.config.ts

> new ProvidePlugin({ jQuery: 'jquery', $: 'jquery', jquery: 'jquery' })

Explanation:
The jquery.signalR.js script is indeed not written as a umd module. Which makes it by default, not to be loadable by webpack. The jquery.signalR.js script doesn't require jquery, but assumes that Jquery lives on the global variable window.jQuery. We can make this work in webpack by importing the jquery module with the expose-loader. This loader will make sure that the exported value of jquery, is exposed to the jQuery global var. Thus allowing to load the signalr.js script as the next module.

Also if you want to later use signalr by using $, you also will have to use the provideplugin for the jquery module. inside webpack.config.js

hannes neukermans
  • 12,017
  • 7
  • 37
  • 56
4

I investigated your problem and found the following solutions:

1) Use

window.jQuery = require("jquery");

to import jQuery in your entry file

2) Change your webpack.config.js

 new webpack.ProvidePlugin({
   jQuery: 'jquery',
   $: 'jquery',
   jquery: 'jquery',
   'window.jQuery': 'jquery' <== add this line
 }),

And then in your entry file:

import 'jquery';
yurzui
  • 205,937
  • 32
  • 433
  • 399
4

I'm not familiar with SignalR but here are the steps how I solved similar problem when trying to make Spectrum jQuery Colorpicker work on my application:

  1. Add libs into package.json file, dependencies section

    "jquery": "3.1.1",
    "spectrum-colorpicker": "1.8.0" 
    
  2. Add typings into package.json file, devDependencies section

    "@types/spectrum": "1.5.27",
    "@types/jquery": "2.0.33",
    
  3. Specify types in tsconfig.json file. Compiler used to throw errors without this entry

    "types": ["jquery", "spectrum"]
    
  4. Add webpack plugin into webpack.common.js

     plugins: [
            new webpack.ProvidePlugin({
                jQuery: 'jquery',
                $: 'jquery',
                jquery: 'jquery'
            })
     ]
    
  5. Add imports into vendor.ts file

    import 'jquery/dist/jquery.js';
    import 'spectrum-colorpicker/spectrum.js';
    import 'spectrum-colorpicker/spectrum.css';
    
  6. Then in your component or directive add the following declare statement

    declare var $ : JQueryStatic;
    
  7. Sample of usage in the code

    $("#" + this.fieldId).spectrum({
                preferredFormat: "hex3",
                showInput: true,
                showPalette: true,
                palette: [["red", "rgba(0, 255, 0, .5)", "rgb(0, 0, 255)"]],
                color: this._color,
                change: this.colorChanged,
     });
    

This is it. These modifications solved my problem and hopefully will help you and save some time to others who will try to make jQuery plugin work on Angular2 application.

Tomas Zuklys
  • 315
  • 1
  • 2
  • 10