Raw js imported as a real module

Modern javascript libraries are all made of modules. They can be plugged inside any project : web, server, batch or program.

That would be really straightforward to include any dependency as a single line of configuration inside a package.json file.

Unfortunately, some teams want to expose web javascript code in a raw format : no ‘export’, no ‘module.exports’, and even nothing injected inside ‘global’ or ‘window’. ES5-like format.

Naive var(s) and function(s) are declared. Private companies do so, and they minify/obfuscate their code.
Some teams even make a javascript code generator when the source code simply cannot be shared with other companies.

//this is a raw javascript file
var foo = "some important data"; 

function bar(){ 
  return "successful."; 
}; 
//This script is unmodifiable
//You are expected to use these symbols, without any access to them.

A simple option would suggest you to copy/paste the library inside your app.
Too bad it affects a lot the quality of your delivery : big chunks, troubles when the library is upgraded but not in your code, ‘package.json’ not explicit (some libs are not visible in the manifest although they are effectively included)

I have found another solution that I wish to share.
1°) Bundle that library in package.json (you can set the URL inside the version).
2°) Then import that lib in your code, but not with the ‘import’ or ‘require’ shortcut… write that boilerplate code :

//it is like an es6 import, excepted the fact that it also collects non exported variables and functions
const _imports = moduleImports => Object.assign({}, ...moduleImports.map(moduleImport => {
    //build a closure outside the non-structured code
    const theModule = new (eval('(function(){' + fs.readFileSync(`${moduleImport}.js`) + ';this.eval = (name) => eval(name)})'))()

    //pick the functions and var names
    const stringified = theModule.constructor.toString()
    const functions = (stringified.match(/function\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(/g)||[]).map(oneFunction => oneFunction.replace(/^function/g, '').replace('(', '').trim())
    const variables = (stringified.match(/(?:var|let|const)\s+([a-zA-Z_][.a-zA-Z_0-9]*)\s*=/g)||[]).map(oneFunction => oneFunction.replace(/^(var|let|const)\s/g, '').replace('=', '').trim())

    //resolve the references inside the module
    return Object.assign({}, ...functions.concat(variables).map(symbol => {try{return {[symbol]:theModule.eval(symbol)}}catch(e){}}).filter(symbol => symbol))
}))

3°) Call the _imports function where needed

// top of your js file
const { foo, bar } = _imports(['my-es5-module-1', 'my-es5-module-2'])
// your other imports
import { Component } from 'react'
// and it works...
console.log(foo)
console.log(bar())

There you go, use the invisible members of the lib like if they were really exported.
In this example, it also works when the lib is a set of javascript files that are dependent on each other but without import.

By the way,
Maybe you noticed that the layout of the blog has changed once again.
I am pretty sure that my visitors will prefer some rich content rather then a beautiful decoration, given the fact that the blog no longer talks about artistic concerns.
That is why I chose the most sober design I could find.

Webpack2 : an example, a real one ?

« Has this ever happened to you ? »
-> You work in a non open minded company, or a company willing to make some progress, but behind in tech.
-> The front part of your stack is in (Java/PHP/Python/You name it) + (naive javascript or some former trendy framework like jquery / backbone / handlebars), and your build tool is as shifted from reality as maven or ant can be.
-> You think you deserve more than to maintain such a legacy stack and to write IE9 compliant code

My solution was to think with Webpack2.

Rather than explaining you what it is, let me define you what it is not :

– Webpack is not (really) a build tool. It would rather be « a module emulation builder ». In other words, it uses all of your resources to bundle them into very few « big files ».
Which means that you will no longer see this :
[Long resources list loading]
…but actually two resources : a webpage and a big script. Which will save the patience of some mobile users, and avoid repetitive server requests to load the same code over and over again.

– Webpack is not a code minifier. It groups css, medias (sound/picture), javascript resources at once. Don’t call that a minifier.

– Webpack is not a compiler. It uses a grammar to filter which resources must be handled, and some rules to declare how they should be transpiled/compressed/grouped/moved/compiled. Actually, it uses some loaders that are able to do the compiling job. Like babel, to be able to code using the latest javascript version (ES2017) while targeting IE9… Like handlebars, even if it is old, if you like it.

– Webpack is not a file manipulation tool. But it can add/change/delete some text inside files, it can copy/cut/paste/zip/unzip some resources. Some plugins are dedicated to such operations, like the CopyWebpackPlugin, or the ExtractTextPlugin.

Enough talk, let’s take an example stack : a « mavened » java webapp with the following js stack :
handlebars, backbone, underscore, jquery, and an invasive homegrown framework to avoid some non homogeneous display.
1°) Start by removing all of the DIY maven plugins. Write this instead in the plugins section:

<plugin>
<groupid>com.github.eirslett</groupid>
                <artifactid>frontend-maven-plugin</artifactid>
                <version>1.3</version>
                <executions>
                    <execution>
                        <id>install node and yarn</id>
                        <goals>
                            <goal>install-node-and-yarn</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <configuration>
                            <yarnversion>v0.23.2</yarnversion>
                        </configuration>
                    </execution>
                    <execution>
                        <id>yarn install</id>
                        <goals>
                            <goal>yarn</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <configuration>
                            <arguments>install</arguments>
                        </configuration>
                    </execution>
                    <execution>
                        <id>webpack</id>
                        <goals>
                            <goal>webpack</goal>
                        </goals>
                        <phase>process-resources</phase>
                        <configuration>
                            <environmentvariables>
                                <node_env>${env}</node_env>
                                <version>${project.version}</version>
                                <m2_repository>${maven.repo.local}</m2_repository>
                                <uitk_version>${uitkCoreVersion}</uitk_version>
                            </environmentvariables>
                            <arguments>--hide-modules</arguments>
                        </configuration>
                    </execution>
                </executions>
                <configuration>
                    <nodeversion>v7.9.0</nodeversion>
                </configuration>
            </plugin>

2°) Start a small package.json, it will be the bootstrap of your webpack pipeline :

{
  "name": "my-webapp",
  "description": "EcmaScript pipeline to build the assets of my-webapp",
  "version": "1.0.0",
  "private": true,
  "devDependencies": {
    "webpack": "latest",
    "copy-webpack-plugin": "latest",
    "extract-text-webpack-plugin": "latest",
    "before-build-webpack": "latest",
    "noop-webpack-plugin": "latest",
    "modernizr-webpack-plugin": "latest",
    "style-loader": "latest",
    "css-loader": "latest",
    "less-loader": "latest",
    "img-loader": "latest",
    "url-loader": "latest",
    "imports-loader": "latest",
    "exports-loader": "latest",
    "babel-cli": "latest",
    "babel-core": "latest",
    "babel-loader": "latest",
    "babel-preset-env": "latest",
    "babel-preset-es2015": "latest",
    "babel-polyfill": "latest",
    "handlebars": "latest",
    "handlebars-loader": "latest",
    "file-loader": "latest",
    "modernizr": "latest",
    "modernizr-loader": "latest",
    "jquery": "latest",
    "unzip2": "latest",
    "underscore": "latest",
    "phoneparser": "latest",
    "intl-tel-input": "latest",
    "backbone": "latest",
    "moment": "latest",
    "i18n-js": "latest",
    "mkdirp": "latest",
    "ncp": "latest",
    "less": "latest",
    "glob": "latest",
    "properties-reader": "latest"
  },
  "engines": {
    "node": ">=7.9.0"
  }
}

3°) Write a small webpack pipeline (wepack.config.js) and test it immediately :

const webpack = require('webpack')
const path = require('path')
const fs = require('fs')
const unzip = require('unzip2')
const glob = require('glob')
const WebpackBeforeBuildPlugin = require('before-build-webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const ModernizrWebpackPlugin = require('modernizr-webpack-plugin'

const javascriptFiles = glob.sync(`js/**/*.js`)
const target = path.join(__dirname, 'target/')

module.exports = {
    name: 'webapp-bundle',
    target: 'web',
    entry:  [{`js/bundles/bundle.js`: javascriptFiles,}], output: { path: target, filename: '[name].js' }, module: { rules: [ { test: /\.js$/, use: [{ loader: 'babel-loader', options: { presets: [['es2015']] } }] }, ] } }

That works, but there are so much work to do for a real webapp if you are not working on a hello world page or a calculator, and over all if you must cope with an homegrown framework from your company

4°) Add some plugins to your pipeline :
– prepare your assets before the build (unzip, copy, …) :WebpackBeforeBuildPlugin
– provide some variables that nobody wants to declare explicitely : jquery ($), underscore or lodash (_) :webpack.ProvidePlugin
– extract your assets in non js files, for example for css files : ExtractTextPlugin
– manipulate the results after the compilation step : CopyWebpackPlugin
my own plugins list looks like this one :

plugins: [beforeBuild, listAllHandlebarsFiles, provideGlobalVariables, new ModernizrWebpackPlugin(), /* compile, */ extractCss, copyResults, minify]

5°) Add some rules to help webpack understands what is supposed to happen for each case :

{
                test: /\.hbs$/,
                use: [{
                    loader: 'handlebars-loader',
                    options: {
                        knownHelpers: ['i18nMsg', 'block', 'include', 'includeJsBundle', 'eq', 'json', 'i18nJs',
                            'partial'],
                        partialDirs: [
                            path.join(__dirname, `${webpackAssetsFolder}views`)
                        ],
                        rootRelatve: `${webpackAssetsFolder}views`
                    }
                }],
            },
            {
                test: /\.js$/,
                use: [{
                    loader: 'babel-loader',
                    options: {
                        presets: [['es2015']]
                    }
                }]
            },
            {
                test: /\.less$/,
                use: extractCss.extract({
                    use: ['css-loader', 'less-loader']
                })
            },
            {
                test: /\.css$/,
                use: extractCss.extract({
                    fallback: 'style-loader',
                    use: 'css-loader'
                })
            },

5°) Adapt your homegrown framework to your pipeline. Unzip the resources of the framework and mix them with yours.

You can have a look at how I did at my work : https://gist.github.com/libetl/79023dec57e4f4a02b48ee05b8d34d68
The pipeline (I mean the webpack.config.js file) can be composed of all these steps (mainly) :

import some modules
definition of resources and paths
definitions of complex plugins
output folder and output bundles
source maps (yes or no ?)
webpack rules (which file for which operation)
plugins list

Please do this at home, or at school. You will make your app more reliable and efficient. Good luck.

ES6 (or Javascript) : how to loop on the same promise

In the era of the promises, who likes to wait for an uncertain amount of time ?

A promise is the key to hope.
No need to setTimeout(function(){}, XXXXX) milliseconds. You don’t know if you waited too much, and even worse… : you don’t know if you did not wait enough.

Actually, you can tell your program to wait for a promise, then check a condition, then chain a new promise if the condition is not met. The only subtle delta to achieve this is to trigger the condition testing and the return value inside functions ; here is an example :


aPromise.then((pollResponse) => {
const promiseWhile = (condition, oldResponse, promiseGenerator) => {
if (!condition(oldResponse)) {
return typeof oldResponse === 'function' ? oldResponse : () => oldResponse
}
return promiseGenerator().then((newResponse) => promiseWhile(condition, newResponse, promiseGenerator))
}

const promiseGenerator = (execute, oldResponse) => {
return promiseWhile((newResponse) => newResponse.code === 'PENDING', oldResponse,
() => execute().then((newResponse) => promiseGenerator(execute, newResponse)))
}

return promiseGenerator(() => query(`/myApi/pollStatus`), pollResponse)
})
.then((pollResponse) => {
const result = pollResponse()
console.log(result.code) //'COMPLETE'
})

Given a method called query, which returns either {code: ‘PENDING’} or {code: ‘COMPLETE’}, This code runs the query method regularly and stops when the value of code is no more ‘PENDING’. But this does not wait for an arbitrary amount of time.

If the condition is not true anymore, it returns a function whose result is the value to fetch.
Else it chains the previously resolved promise with a promise calling query again and checking the same condition again.

That is all.

There is also a lighter version without value return, and where ‘query’ is immediate (actually, it occurs within condition()), but unfortunately you have to define a small interval to avoid saturation on your event loop :


const waitWhile = (condition, resolve) => {
if (!condition()) {
resolve()
}
setTimeout(() => waitWhile(condition, resolve), 1)
}

JIRA command line (jilla)

J’ai récemment intégré un outil en ligne de commande pour avoir des informations rapides sur une issue JIRA sans me rendre sur l’interface web et naviguer parmi les dashboards.

Cet outil, pratique lorsque l’on travaille dans un shell, permet de ne pas être déconcentré pendant son activité de développement.
Il s’installe en tant que package de NodeJS en utilisant la commande npm install -g jilla.

Seuls soucis : il ne passe pas les proxy, et ne s’adapte pas aux états autres que OPEN, RESOLVED, NEEDINFO, CLOSED.
Pour outrepasser ce problème, j’ai forké le repository et j’ai amélioré cette prise en charge.
J’ai également écrit une petite méthode pour obtenir en sortie console les infos du Sprint Scrum actuel sur JIRA Agile.
J’ai aussi écrit un petit script pour que l’id de l’issue actuelle soit devinée à partir de la branche de développement git sur laquelle on travaille.

Ce fork se trouve à l’adresse https://github.com/libetl/jilla/

Pour l’obtenir (que cette modif soit intégrée ou non dans la prochaine version de cet outil), il vous faut copier les fichiers gira et jilla dans votre dossier /usr/local/bin (ou /usr/bin). Puis (re)lancer la configuration via jilla config.

Un nombre est-il premier ? en une ligne

Un collègue m’a soumis le code suivant :


<script type="text/javascript">
function prime (i){return /^(?!(11+)\1+$)/.test (Array.apply(null, new Array(i)).map(Number.prototype.valueOf,1).toString().replace (/,/g, ""));}
</script>

C’est très intelligent mais très obfuscant.
Imaginez que votre nombre n devienne 11..1 (n fois). (code réalisé par l’expression Array.apply(null, new Array(i)).map(Number.prototype.valueOf,1).toString().replace (/,/g, «  »));)
Le principe de la regex est de s’assurer que la chaîne passée en paramètre n’est pas précédée d’un 1 lors de son recoupage. L’algo de test de la regex va d’abord s’assurer que 11..1 n-1 fois ne soit pas capturé par le groupe \1 (vraisemblablement il y a peu de chance que ce soit le cas), sinon il va recouper avec n – 2, et ainsi de suite jusqu’à 2.

S’il y arrive, c’est que n est divisible par le nombre utilisé pour la recoupe. Si aucune recoupe n’a marché, l’expression régulière sera valide et en fait sa condition est nécessaire et suffisante pour prouver que n est premier.

J’enquéris.

Il ne faut jamais dire jamais.
J’ai plutôt préféré par le passé utiliser dojo de préférence à jquery, mais aujourd’hui c’est bien ce dernier qui change notre façon de voir un site aujourd’hui.

Pour preuve, je me suis codé une petite page web de slideshow vertical avec parallax.
Slideshow jquery

Et si vous voyez des petites étoiles qui défilent au milieu de l’écran, n’y voyez là aucun effet hallucinatoire.

Draw2d et Dojo : et ce n’est que du javascript ?

Editeur d'algorithme

Ce que je vous presente ce soir utilise un langage pauvre, atypique et pourtant a forte valeur ajoutee : javascript, encore et toujours…

Je tiens a vous montrer les possibilites etonnantes d’un framework de DAO javascript : http://www.draw2d.org

Voici ce que j’ai pu realiser en une journee de temps avec draw2d (et dojo pour l’interface graphique) : http://libe.toile-libre.org/diagramme/ . Il s’agit d’un debut d’editeur d’algorithme.

Pourquoi faire ? J’ai ma petite idée mais je n’en dirai rien pour l’instant.

Comment ca je devrais bosser ?!

Justement, je commence en fait a avoir une vraie idée de ce sur quoi je reverais de bosser : du BPMN, du MDD, soyons fous !