Projects:JS Formatter Upgrade/Specs
Contents |
Requirements
Background
In the recent years, Javascript has experienced a number of changes, and there are lots of language improvements and technologies availables such as lambda expressions, JSX, React, Typescript, etc. that are not supported with our current version of code formatter (JSBeautifier) and linter (JSLint4Java 1.4.7, released in 2011). For this reason, an upgrade is required to improve code style and add suppport for new technologies that can potentially be used in the future.
Goals
Remove JS code linting after compressing
In ComponentGenerator.java, JSLint is invoked when the component to process module is in development, adding an extra overhead to this step. This step is removed, and therefore we can remove the dependency of lib/runtime/jslint4java-1.4.7.jar.
Replace JSLint with ESLint
A linter is a tool that analyzes code to detect potential errors, bugs or code style issues. For this project it is proposed to migrate from out current linter (JSLint) to the latest version of ESLint, which is 5.13.0, released in February 2019
Replace JS Beautifier with Prettier
A code formatter is a tool that ensures all codebase follows a certain set of rules, making code uniform and easier to maintain.
Available Alternatives
For this purpose, 3 formatters were considered in this project:
- ESBeautifier
ESBeautifier formatter can be integrated seamlessly in Openbravo's workflow, but it looks like it has few maintainers and it is not updated quite frequently.
- JS Beautifier
JS Beautifier could be the obvious choice as it's the one currently used for Openbravo, although we use an old version. It is a mature project, and have a large amount of downloads every week, so its still used by the community, but it seems that they're lacking in contributors for the project, and for this reason there are features that are not currently implemented such as JSX support.
- Prettier
Prettier is a relatively new project which gained a lot of traction (currently having almost 3 million weekly downloads in npm). It is used by people like Facebook (React), Paypal, mongoDB, Discord or yarn. Supports lots of new technologies such as JSX/React, Vue, Angular, Typescript, etc. and has a nice support for all newer frontend IDEs (Atom, VSCode). This is an opinionated formatter, meaning that it has quite few configuration options, so its likely that it will result in lots of changes when applied in Openbravo codebase.
Update Lint/Formatter rules
Upgrading the tools is a good opportunity to review and update the linting and formatting rules used in our codebase. The rule followed for this is to include rules to enforce us to follow good coding practices but without being too disruptive with the current codebase.
Rules used by ESLint and Prettier can be found in the Openbravo project root:
- .eslintrc.json
- .prettierrc.json
This way they can be autodetected by most IDE plugins.
Configuration Guide
Setup
In order to run the Javascript formatter and linter, it is required to install npm in the development machine.
> sudo apt install npm
Once npm is available, required packages can be installed running the following command in Openbravo project root:
> npm install
This will install a local copy of ESLint and Prettier for the current project using the version defined in package.json.
Usage
You can use the formatter/linter in 3 different ways:
Standalone script
Instead of having several scripts depending on whether you want to check a particular file or all project files, or if the file being checked belonged to a core or a module, all of these were simplified in one single script:
- Formatter: modules/org.openbravo.client.kernel/jsformatter/jsformatter
- Linter: modules/org.openbravo.client.kernel/jslint/jslint
Both commands with no arguments, runs ESLint/Prettier to all .js files in the project except the ones matched by .jsexclude (see Ignoring js Files for more info).
If passing the path to one or more .js file, check will be performed to those files.
At the beginning, these commands prints the number of files to process. If you want to see the path of all the files being processed, execute with the -v option.
To see all options available, run with the -h flag.
Mercurial hook
Same as the standalone scripts, both linter and formatter are available as mercurial hooks as well
- Formatter: modules/org.openbravo.client.kernel/jsformatter/jsformatter-hg
- Linter: modules/org.openbravo.client.kernel/jslint/jslint-hg
These scripts can be used both for developments in Core and in modules. To use them, add the following lines in your global .hgrc file:
[hooks] pretxncommit = <openbravo path>/modules/org.openbravo.client.kernel/jslint/jslint-hg pre-commit = <openbravo path>/modules/org.openbravo.client.kernel/jsformatter/jsformatter-hg
IDE Plugins
Visual Studio Code
Visual Studio Code supports both ESLint and Prettier via extensions:
To setup ESLint, it is required to define the location of the node_modules folder used by Openbravo. In settings.json:
{ ... "eslint.nodePath": "<path_to_openbravo>/modules/org.openbravo.client.kernel/", ... }
For Prettier, in order to use our config file to format, the following option should be enabled: "Prettier: Require Config", or in settings.json:
{ ... "prettier.requireConfig": true, ... }
IntelliJ
IntelliJ Ultimate has built-in support of ESLint and supports Prettier via Plugin.
- ESLint: In Settings, enable ESLint and define the Node interpreter and ESLint package locations.
- Prettier: Install the JetBrains's Prettier plugin and in the Settings screen, just define the location of the Node interpreter and the Prettier package. Then you can format the file using Prettier with Ctrl+Alt+Shift+P or the context menu.
Sublime Text
ESLint just works by installing SublimeLinter and then SublimeLinter-eslint packages using PackageControl.
Prettier can be used by installing the package JsPrettier in PackageControl. By default, this plugin will search for the Prettier CLI in the following order:
- Locally installed prettier, relative to the Sublime Text Project file's root directory.
- User's home directory
- JsPrettier Sublime Text plug-in directory
- Globally installed prettier
If none applies, it is required to introduce the path of the Prettier CLI in JsPrettier settings (Preferences|Package Settings|JsPrettier):
{ ... "prettier_cli_path": "<path_to_openbravo>/modules/org.openbravo.client.kernel/node_modules/.bin/prettier", ... }
Atom
Atom supports both ESLint and Prettier via packages.
Ignoring js files
In previous versions, certain javascript files/directories can be ommited adding a rule in jscheck/jsfiles. The downside of this approach is that if any module requires to ignore certain paths, it should be included in this file even if the module is not needed in the current project.
Both ESLint and Prettier supports the use of .ignore files to define which files/folder should be ignored from linting/formatting. In the root folder of Openbravo, a .eslintignore and .prettierignore file is included to define the files to be ignored for the Core modules and all installed modules that hasn't included the ignore files yet. Each module can define their own ignore files and place them in their root folder. Another advantage of this approach is that IDEs supports these files and ignore lint warnings and doesn't try to format ignored files.
Ignore files follows the same syntax as .gitignore/.hgignore. For example, considering this ignore file:
qunit/ docs/ LAB*.js benchmark/ BigDecimal*.js scopeleaks*.js *smartclient*
This file will make Prettier/ESLint ignore the contents of any docs or benchmark folder. Using the * wildcard allow us to ignore any variation of LAB.js (files named LAB.js, LAB-1.0.0.js or LAB.min.js will be ignored) and the last line ignores any appearance of smartclient both in the path of the file.
In case you want to completely ignore a module for Javascript checks, you can just add an empty .jsignore file. Modules with this file will be completely ignored in the bundled scripts and avoids showing an error message about executions of ESLint without providing a valid .js file. (See ESLint issue 10587 for details)