One of the biggest advantages of Oracle JET is, that we have a toolkit instead of a framework. This means, we are easily able to add third party libraries into our stack. When you take a look at all those javascript libraries out there, you will realize that the pain is to choose the right library for the right purpose.
With version 2.2 you had to rely on bower to add components or libraries. Now in version 3 everything is about NPM. In my opinion it is great that they switched from to different package managers to only one.
Let’s take a closer look on how to add an additional Library to a new Oracle JET app. One Library I often use is socket.io. Lets create a simple example app with socket.io integration.
yo oraclejet socketIoIntegration --template=basic
Basic structure

Basic Oracle Jet application structure

After creating the application structure with basic template we can see the difference to version 2.2 applications. The bower_components folder and the bower.json are missing.
Assuming we want to create a ORACLE JET App that works as a client and will connect to a socket.io server instance.
First we need do reference the correct library in package.json.
{
  "name": "v7-LED-APP",
  "version": "1.0.0",
  "description": "virtual7 LED APP",
  "author": {
    "name": "Enno Schulte",
    "homepage": "https://blog.virtual7.de"
  },
  "dependencies": {
    "oraclejet": "~3.0.0",
    "socket.io-client": "*"
  },
  "devDependencies": {
    "font-awesome": "^4.7.0",
    "grunt": "^1.0.1",
    "grunt-oraclejet": "~3.0.0",
    "load-grunt-config": "0.19.2",
    "node-sass": "^4.2.0",
    "oraclejet-tooling": "~3.0.0",
    "ws": "2.3.1"
  },
  "engines": {
    "node": ">=0.10.0"
  },
  "private": true
}
After a short „npm update“ the socket.io-client library files are added to the node_modules folder.
Basic structure

Basic Oracle Jet application structure

Project structure with integrated socket.ioSeems like we have all we need to get started. Now comes the tricky part. To use our newly added library we need to make a reference in the oracle jet-build.js script. In older versions you had to add your 3rd party libraries to a bower-copy task. Now all we need to do, is to tell this build script from where to where it should copy our library files.

Therefore we have the task copyCustomLibsToStaging where we can define a source and a destination path. You can specify a filter if you don’t want to move all files from the source to the destination directory.
copyCustomLibsToStaging: {
  fileList: [{cwd: 'node_modules/socket.io-client/dist/',
              src: ['**', '!test.js'],
              dest: 'web/js/libs/socket.io-client'}]
},
For more information regarding the copyCustomLibsToStaging task, you can find a detailed description right at oracle  https://docs.oracle.com/middleware/jet300/jet/developer/GUID-EC40DF3C-57FB-4919-A066-73E573D66B67.htm#JETDG-GUID-EC40DF3C-57FB-4919-A066-73E573D66B67
Now that we know where our libraries are placed, we can update the „main-release-paths.json“ and add our library.
{
  "knockout": "libs/knockout/knockout-3.4.0",
  "jquery": "libs/jquery/jquery-3.1.0.min",
  "jqueryui-amd": "libs/jquery/jqueryui-amd-1.12.0.min",
  "promise": "libs/es6-promise/es6-promise.min",
  "hammerjs": "libs/hammer/hammer-2.0.8.min",
  "ojdnd": "libs/dnd-polyfill/dnd-polyfill-1.0.0.min",
  "ojs": "libs/oj/v2.2.0/min",
  "ojL10n": "libs/oj/v2.2.0/ojL10n",
  "ojtranslations": "libs/oj/v2.2.0/resources",
  "text": "libs/require/text",
  "signals": "libs/js-signals/signals.min",
  "socket.io": "libs/socket.io-client/dist/socket.io.slim"
}
Two steps are left to use socket.io in oracle JET. First we need to add the library to the require.js configuration. So that it will be loaded if we need it. That can be done in the „main.js“ file.
Just add socket.io-client like the other libraries. Be carefull to use the same path as defined in  „main-release-paths.json“.
requirejs.config(
    {
        baseUrl: 'js',

        // Path mappings for the logical module names
        paths: //injector:mainReleasePaths
            {
                'knockout': 'libs/knockout/knockout-3.4.0.debug',
                'jquery': 'libs/jquery/jquery-3.1.1',
                'jqueryui-amd': 'libs/jquery/jqueryui-amd-1.12.0',
                'promise': 'libs/es6-promise/es6-promise',
                'hammerjs': 'libs/hammer/hammer-2.0.8',
                'ojdnd': 'libs/dnd-polyfill/dnd-polyfill-1.0.0',
                'ojs': 'libs/oj/v3.0.0/debug',
                'ojL10n': 'libs/oj/v3.0.0/ojL10n',
                'ojtranslations': 'libs/oj/v3.0.0/resources',
                'text': 'libs/require/text',
                'signals': 'libs/js-signals/signals',
                'customElements': 'libs/webcomponents/CustomElements',
                'proj4': 'libs/proj4js/dist/proj4-src',
                'css': 'libs/require-css/css',
                'socket.io': 'libs/socket.io-client/socket.io.slim',
                'colorModel': 'models/colorModel'
            }
        //endinjector
Since our socket.io-client doesn’t expose a AMD config, we need to register a shim.
// Shim configurations for modules that do not expose AMD
        shim: {
            'jquery': {
                exports: ['jQuery', '$']
            },
            'socket.io': {
                exports: ['io']
            }
        }
    }
);
Now we are ready to go.
Just add socket.io like any other package in the require fields of your ORACLE JET application. Remember the shim we defined. Because of that we can add a variable that will reference our library. Take a look at the function parameters. See the variable “io”. That can be used to make a connection to a socket.io server instance.
In my example I am only logging the protocol version. If you want to make a real connection you have to use “io.connect(http://your.url.goes.here);”
require(['ojs/ojcore', 'knockout', 'appController', 'socket.io', 'ojs/ojknockout',
        'ojs/ojmodule', 'ojs/ojrouter', 'ojs/ojnavigationlist', 'ojs/ojbutton', 'ojs/ojtoolbar'],
    function (oj, ko, app, io) { // this callback gets executed when all required modules are loaded

        $(function () { 

            console.log('Socket.IO Protocol: ', io.protocol);

            function init() {
                oj.Router.sync().then(
                    function () {
                        // Bind your ViewModel for the content of the whole page body.
                        ko.applyBindings(app, document.getElementById('globalBody'));
                    },
                    function (error) {
                        oj.Logger.error('Error in root start: ' + error.message);
                    }
                );
            }

            // If running in a hybrid (e.g. Cordova) environment, we need to wait for the deviceready
            // event before executing any code that might interact with Cordova APIs or plugins.
            if ($(document.body).hasClass('oj-hybrid')) {
                document.addEventListener("deviceready", init);
            } else {
                init();
            }

        });

    }
);
Now our console log should look like this:
Console output of socket.io integrated app

Console output of socket.io integrated app

For more information about adding third party libraries to oracle jet:

For more information about socket.io-client: