Facebook has announced its experimental JavaScript tool chain Rome as open source. Rome is the new work from Babel and Yarn author Sebastian McKenzie, a member of the React Native team. Before open source, Rome was mostly Sebastian McKenzie’s one-man project, but Facebook was willing to pay him to work on it.

The Rome Project is at github.com/facebookexp… .

The name Rome is the third name for the program. In 2016, Sebastian McKenzie first named the project Sonic, “for speed”, and later Hydra, “for multiple heads”. Change to Rome in March 2019 because “There are many perfectly appropriate metaphors for Rome, such as” Rome wasn’t built in a day “and” all roads lead to Rome “(twitter.com/sebmck/stat…) .

This is Sebastian McKenzie’s Logo for Rome:

Someone said, “Isn’t that a Spartan helmet?”

Sebastian McKenzie replied: “Yes, a Spartan helmet, Greek. It’s not Roman. Never mind, I don’t care.”

What is Rome?

According to the project introduction:

  • Rome is an experimental JavaScript toolchain that includes compilers, linters, formatters, packers, test frameworks, and more, and aims to be a comprehensive tool for working with JavaScript source code;
  • Rome is not a patchwork of existing tools; all of its components are written from scratch without using third-party dependencies;
  • Rome aims to replace many existing JavaScript tools.

Rome is written entirely in TypeScript, with all code in a repository that separates functional components as internal packages. Rome is also self-hosted, and you can compile yourself. Rome supports JSX as well as Flow and TypeScript annotation code. Currently, Rome is focused on Linting: github.com/facebookexp… .

As for how to use Rome, officials mention that only building from source is supported. This article concludes by explaining how to get Rome running.

What Rome looks like

As stated on the project page, Rome is currently under development and cannot be used in an actual project. However, its CLI help provides an overview of the features currently available in Rome.

Source code command

  • analyzeDependencies: Analyzes and outputs file dependencies
  • bundle: Package JavaScript as a file
  • compile: Compiles JavaScript files
  • develop: Starts the Web server
  • parse: Parses the JavaScript file and outputs the AST
  • resolve: Calculates the file path

Code quality command

  • ci: Secure dependencies, run Linter and tests
  • lint: Run Linter on the file
  • test: Run tests

Process Management commands

  • restart: Restarts the daemon
  • start: Starts the daemon
  • status: Gets the current daemon state
  • stop: Stops the running daemon
  • web

Project Management Commands

  • config
  • publish: TODO
  • run: TODO

Internal command

  • evict: Expels files from the memory cache
  • logs
  • rage

packaging

Rome’s packaging process is unique in that all compilation is done in modules, each of which is handled by a worker thread pool. This process is fine for translating individual modules, but can be problematic for packaging, such as reparsing modules that have already been parsed by other worker threads. To do this, you need to pre-populate your modules with namespaces so that they all share a scope.

Rome prefixes each variable in a module scope, which is an identifier generated based on the module name. For example, the variable foo in test.js will become test_js_foo.

Likewise, the import and export identifiers for each module are treated the same way. Thus, the export of any module can be identified by the name of the module and the name of the export.

Output 1.

For example, modulea.mjs (the.mjs extension required when Rome packages modules) contains the following exported variables:

export const myVar = 'hello'

Copy the code

Another module file, module.mjs, imports this module:

import { myVar } from './moduleA.mjs'

Copy the code

Run:

rome bundle mudule.mjs dist

Copy the code

The following index.js file is generated in the dist directory:

(function(global) { 'use strict'; // rome-root/moduleA.mjs const ___R$rome$root$moduleA_mjs$myVar = 'hello'; // rome-root/module.mjs const ___R$rome$root$module_mjs = {}; console.log(___R$rome$root$moduleA_mjs$myVar); return ___R$rome$root$module_mjs; })(typeof global ! == 'undefined' ? global : typeof window ! == 'undefined' ? window : this);Copy the code

Thus, Rome’s packaged files are similar to Rullup, in that all modules are pushed into a shared closure scope, as opposed to Webpack, where each module has a closure and these closures are strung together through a runtime loader.

2. Complex examples

Let’s try a closer example.

Entry. TSX:

import React from './react';  
import title from './other';  

async function App(props: any) {  
  return <div id="app">{await title()}</div>
}

App({}).then(console.log);  

Copy the code

Other. TSX:

import React from './react';  
export default () => <h1>Hello World</h1>;  

Copy the code

The react. TSX:

type VNode = { type: string; props: any; children: Array<VNode|string> }; function createElement( type: string, props: any, ... children: Array<VNode|string> ): VNode { return { type, props, children }; } export default { createElement };Copy the code

To run Rome Bundle Entry. TSX bundle:

➜ Rome git:(master) qualify Rome bundle entry. TSX bundle ⚠ Disk caching has been disabled due to the ROME_CACHE=0 environment Variable ⚠ ℹ Bundling packages/@romejs/cli/bin/rome.ts searchable the following files to/TMP/rome-dev-index.js 2.41MB Map 95B sourcemap-bundleBuddy. Json 473kB stats ⚠ Disk caching has been disabled due to the ROME_CACHE=0 environment variable ⚠ ℹ Bundling entry. TSX searchsaved the following files to bundle-index.js 907B entry - index.js.map 95B sourcemap - bundlebuddy.json 293B statsCopy the code

The following index.js file is generated in the bundle directory:

(function(global) { 'use strict'; // rome-root/react.tsx function ___R$$priv$rome$root$react_tsx$createElement(type, props, ... children) { return {type: type, props: props, children: children}; } const ___R$rome$root$react_tsx$default = { createElement: ___R$$priv$rome$root$react_tsx$createElement }; // rome-root/other.tsx const ___R$rome$root$other_tsx$default = () => ___R$rome$root$react_tsx$default.createElement('h1', null, 'Hello World'); // rome-root/entry.tsx const ___R$rome$root$entry_tsx = {}; async function ___R$$priv$rome$root$entry_tsx$App(props) { return ___R$rome$root$react_tsx$default.createElement('div', { id: 'app'}, (await ___R$rome$root$other_tsx$default())); } ___R$$priv$rome$root$entry_tsx$App({}).then(console.log); return ___R$rome$root$entry_tsx; })(typeof global ! == 'undefined' ? global : typeof window ! == 'undefined' ? window : this);Copy the code

At first glance it seems a bit messy, but it’s easy to understand when you subtract the module-specific code:

(function(global) { 'use strict'; // rome-root/react. TSX const ___R$Rome $root$react_tsx$default = /* omit */ / rome-root/other.tsx const ___R$Rome $root$entry_tsx = {}; ___R$Rome $root$other_tsx$default = /* omit */ / Rome -root/ entry_tsx const ___R$Rome $root$entry_tsx = {}; / * omitted * / ___R $$$$$entry_tsx root Rome priv $App ({}). Then (the console. The log); return ___R$rome$root$entry_tsx; })(window);Copy the code

In fact, it’s the same as the simple example above: all three modules are plugged into a closure.

Help information

Run Rome — Help to see the current “complete” help information for Rome:

➜ ~ Rome --help ⚠ Disk caching has been disabled due to the ROME_CACHE=0 environment variable ⚠ ℹ Bundling ✔ Rome.ts save the following files to/TMP/rome-dev-index.js 2.41MB Projects/_projects/ packages/@romejs/cli/bin/ Rome entry - index.js.map 95B sourcemap - bundlebuddy.json 473kB stats Usage: rome [command] [flags] Options --benchmark no description found --benchmark-iterations <num> no description found --collect-markers no description found --cwd <input> no description found --fieri no description found --focus <input> no description found --grep <input> no description found --help show this help screen --inverse-grep no description found --log-path <input> no description found --logs no description found --log-workers no description found --markers-path <input> no description found --max-diagnostics <num> no description found --no-profile-workers no description found --no-show-all-diagnostics no description found --profile no description found --profile-path <input> no description found --profile-sampling <num> no description found --profile-timeout <num> no description found --rage no description found --rage-path <input> no description found --resolver-mocks no description found --resolver-scale <num> no description found --silent no description found --temporary-daemon no description found --verbose no description found --verbose-diagnostics no description found --watch no description found Code Quality Commands ci install dependencies, run lint and tests lint run lint against a set of files test run tests --no-coverage no description found --show-all-coverage no description found --update-snapshots no description found Internal Commands evict evict a file from the memory cache logs rage Process Management Commands restart restart daemon start start daemon (if none running) status get the current daemon status stop stop a running daemon if one exists web Project Management Commands config publish TODO run TODO Source Code Commands analyzeDependencies analyze and dump the dependencies of a file --compact no description found --focus-source <input> no description found bundle build a standalone js bundle for a package compile compile a single file --bundle no description found develop start a web server --port <num> no description found parse parse a single file and dump its ast --no-compact no description found --show-despite-diagnostics no description found resolve resolve a fileCopy the code

Get Rome running

As mentioned earlier, Rome has not yet shipped the NPM package, so it can only be used in code. First, clone its Github repository:

git clone [email protected]:facebookexperimental/rome.git

Copy the code

And then:

cd rome

Copy the code

Last run:

scripts/dev-rome --help

Copy the code

Refer to the link

  • Rome Project: github.com/facebookexp…
  • Rome, a new JavaScript Toolchain: jasonformat.com/rome-javasc…
  • Rome official Announcement: twitter.com/sebmck/stat…
  • Rome Track: twitter.com/sebmck/stat…
  • About Spartan helmets: twitter.com/sebmck/stat…