FIXED: SPFx HelloWorld build Errors preventing gulp build –ship: Browserslist: caniuse-lite is outdated

I recently came across the following erring during a HelloWorld build process – this was preventing my build from being able to ship.

 

PS C:\REpo\SPFest2019-1> gulp bundle –ship
Build target: SHIP
[17:27:17] Using gulpfile C:\REpo\SPFest2019-1\gulpfile.js
[17:27:17] Starting gulp
[17:27:17] Starting ‘bundle’…
[17:27:17] Starting subtask ‘configure-sp-build-rig’…
[17:27:17] Finished subtask ‘configure-sp-build-rig’ after 80 ms
[17:27:17] Starting subtask ‘pre-copy’…
[17:27:18] Finished subtask ‘pre-copy’ after 98 ms
[17:27:18] Starting subtask ‘copy-static-assets’…
[17:27:18] Starting subtask ‘sass’…
[17:27:18] Finished subtask ‘copy-static-assets’ after 203 ms
Browserslist: caniuse-lite is outdated. Please run next command `npm update`
[17:27:18] Finished subtask ‘sass’ after 416 ms
[17:27:18] Starting subtask ‘tslint’…
[17:27:19] [tslint] tslint version: 5.12.1
[17:27:19] Starting subtask ‘tsc’…
[17:27:19] [tsc] typescript version: 2.9.2
[17:27:24] Finished subtask ‘tsc’ after 4.54 s
[17:27:24] Finished subtask ‘tslint’ after 6.5 s
[17:27:24] Starting subtask ‘post-copy’…
[17:27:24] Finished subtask ‘post-copy’ after 318 μs
[17:27:24] Starting subtask ‘collectLocalizedResources’…
[17:27:24] Finished subtask ‘collectLocalizedResources’ after 5.15 ms
[17:27:25] Starting subtask ‘configure-webpack’…
[17:27:26] Finished subtask ‘configure-webpack’ after 1.43 s
[17:27:30] Finished subtask ‘webpack’ after 3.78 s
[17:27:30] Starting subtask ‘configure-webpack-external-bundling’…
[17:27:30] Finished subtask ‘configure-webpack-external-bundling’ after 998 μs
[17:27:30] Finished subtask ‘copy-assets’ after 50 ms
[17:27:30] Starting subtask ‘write-manifests’…
[17:27:31] Finished subtask ‘write-manifests’ after 1.51 s
[17:27:31] Finished ‘bundle’ after 14 s
[17:27:32] ==================[ Finished ]==================
[17:27:32] Project sp-fest-2019-1 version:0.0.1
[17:27:32] Build tools version:3.9.26
[17:27:32] Node version:v8.11.4
[17:27:32] Total duration:19 s
The build failed because a task wrote output to stderr.

Solution

The solution is not immediately obvious – because the use of the caniuse-lite browserslist is not part of my package.json. It is buried somewhere deep inside of the SPFx code provided by Yeoman.

The solution sof npm update did not work.

After a little googleing the following solved the issue – and taught me about npm update 🙂

npm update –depth 10 caniuse-lite browserslist

PS C:\REpo\SPFest2019-1> npm update –depth 10 caniuse-lite browserslist
npm WARN @uifabric/utilities@6.45.1 requires a peer of @types/react-dom@>=16.3.0 <17.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN ajv-keywords@3.4.0 requires a peer of ajv@^6.9.1 but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {“os”:”darwin”,”arch”:”any”} (current: {“os”:”win32″,”arch”:”x64″})

+ browserslist@4.8.2
+ caniuse-lite@1.0.30001015
added 2 packages and updated 3 packages in 29.744s

and that solved the issue.

 

XPages and Bluemix: How to create a Websockets message without being connected to the application

In this article I demonstrate how to create a Websocket message to be broadcast, from a website which is not connected to the Websocket directly. This will be achieved by using a http POST request of the message to a node.js server hosted on Bluemix and having that server then emit a Websocket message out to the application.

Introduction

In the previous article I demonstrated how to create an XPages chat client using a Bluemix hosted node.js server. I was able to do this by porting the node.js example to an XPage (xSocket.xsp). What I wanted to figure out (thank you Stack Overflow) was how to trigger a Websocket message to be sent out without using the Websocket socket.io JavaScript client.

Reference articles

This article is based on information already published on the following blog posts:

POSTing to a node route

In the Watson translation service example article I discussed how to create a new POST route within your node application using the simple express construct “app.post”.


var cors = require('cors');
app.use(cors());

var corsOptions = {
  origin: 'http://copper.xomino.com'
};

app.post('/xpages', cors(corsOptions), function(req, res){
  .....
});

In a similar fashion in this example I am going to POST data from the copper.xomino.com website and therefore I need to add the cors code to the application to allow this.

Looking at the message payload

If we look at the client.js file from the original node.js Bluemix example blog post we can see that the message which is sent to the websocket looks like this

    var msgField = $('#msg'),
    data = { msg: msgField.val(), nickname: nickname, when: new Date() };

So our target is to recreate that same data Object and send it through to the server socket emitter in the same format.

Creating the POST data

Once again learning from the previous Watson example the code for this is relatively simple. We create the data Object with a nickname and text value and then POST them to the xominosocket.mybluemix.net site. Logging the response from the server

var data = {
	nickname: 'marky ajax',
	text: 'Sample POST from AJAX'
}
console.log(data)
$.ajax({ url:
	"http://xominosocket.mybluemix.net/xpages",
	type: "POST",
	data: data
}).done(function( msg ) {
	console.log( msg);
});

Modifying the node.js code

The node.js code from the previous article needs to be updated in a number of ways.

The Watson Translation example used a version of express 3.x. Version 4 is more streamlined and does not contain a lot of middleware. When we attempt to POST data to the node server it cannot be understood because it is encoded by the web browser (by default). For his we need to add the npm module body-parser (not forgetting to include it in the package.json).

The new package.json looks like this

{
  "name": "xominosocket",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.10.1",
    "jade": "^1.7.0",
    "redis": "^0.10.3",
    "socket.io": "^1.2.0",
    "cors": "2.4.2",
    "body-parser": "1.9.2"
  }
}

The app.post also needs to be able to parse the incoming POST and then re-purpose this into a socket emit event. We do this as follows. I also added a check to make sure the req.body was coming through. This was failing before I realized I needed body-parser.

// Handle the form POST containing the text and nickname
app.post('/xpages', cors(corsOptions), function(req, res){
  var request_data = {};

  console.log(req.body)

  if (req.body){
    request_data = {
      'txt': req.body.text,
      'nickname': req.body.nickname
    };
  } else {
    request_data = {
      'txt': 'this failed',
      'nickname': 'Not this guy'
    };
  }

  var data = { msg: request_data.txt, nickname: request_data.nickname, when: new Date() };
  io.sockets.emit("msg", data);
  res.send(data);
});

Testing the new capability

For the purposes of this article I am only going to show the example in Firebug console. As you can see from the code on the right we are posting to the xominosocket site. On the left you can see the communication was successfully sent to the site, the response and the headers:

ws1

From the next screenshot you can see that the message is them broadcast out to the other client currently connected to the socket, in this case in Chrome.

ws2

Cors security

The cors security only allows POSTing from the copper.xomino.com site. This is a good thing 🙂

ws3

Conclusion

In this article we have seen how we can “create” a websockets emission event on the server by POSTing a message to a separate page within the application.

While this may seem pointless (“because why couldn’t I just create a normal websockets message from the page”), what we will see in a future article is the need to emit an event from the server which is not connected to the Websocket and doesn’t need to be.

 

Oh duh, that is why Node Package Manager (npm) is so cool

I am in the process of playing with Bluemix and part of the reason or this is to learn more about node.js. It is really cool to learn something new and also to broaden the mind. But I digress – Node Package Manager (npm) makes using node.js so simple it is mind boggling…

Without going into masses of detail on node.js (which I might at some point) here is the simple example of what I am trying to do and why npm is so cool. Node Package Manager (npm) allows you to install any node “module” or code component library, very easily and with the minimum of effort.

I run node.js on my windows machine within a certain directory. I am looking into CORS enable one of my Bluemix applications so I am messing with the cors module in node.

Here is my directory structure to start with. It is only a simple hello world app but for the sake of this demonstration it is all I need.

n1

Within node_modules we have the following packages which are the modules I used as I was learning the hello world example.

n2

Adding a new module using npm could not be simpler

To add “cors” to my application I open the hello-world directory in a command prompt (Shift right click)

n3

I install cors with the simple “npm install cors” (yes Ryan I used a Command Line Interface)

n4

The files are downloaded from the npm website and they are added to my directory structure

n5

and it is as simple as that. I now have all the cors code which can be accessed by my application.

It only struck me this morning as to the sheer brilliance of this as I “muscle memory” did this to install a new module because it occurred to me I needed it. Simplicity is a thing of beauty to me.

In summary

  • I wanted to install a new module
  • The npm architecture with node centralizes all the code modules you need
  • I did not need to know where to look for the cors package existed
  • I found my example of how to use CORS online
  • I added the code module I needed to my application with 3 words
  • so cool 🙂