Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use all files in a folder like a one big JS

Is it possible to configure ESLint in WebStorm so functions, variables, etc. are parsed also from files in the same folder? In my build process, I concatenate all files in the same folders into big closures, for example:

   src/
      main/          ===> "main.js"
          api.js
          init.js
          ui.js
          constants.js
          .
          .
      renderer/      ===> "renderer.js"
          core.js
          events.js

I would like ESLint to treat all those files just like one, so I don't get "undef" errors for things that are defined.

If it can't be done automatically, I wouldn't mind to create a manual configuration specifying all those files if that is possible.

EDIT: Why I don't (can't) use modules? TLDR- legacy code and project requirements.

  • I need to minify all code. Current closure compiler can transpile ES6 into ES5, but I found some ES6 features very prone to produce broken code. So I am forced to use ES5.

  • As I need ES5. I would only be able to use require() to use modules. Now that's a problem, as require() is a dynamic include and it impacts performance on my context (big electron app for modest power devices)

So to answer @Avin_Kavish, I agree what I do is "technically non conforming", but at the end of the build process it is, because each folder has been grouped into a file. That file is the module or the script. To group the files I use a Gradle plugin https://github.com/eriwen/gradle-js-plugin, I inject a "closure header" and a "closure footer", and all the files in between in the order I want.

Despite the inconvenience, at the end I get super-compact nodeJS code, with all methods obfuscated, etc.

I ended up using @Patrick suggestion, thanks for that!

EDIT 2

WebPack + Electron-WebPack turned out to be what I was looking for.

BTW- I think the proper way to do this is if EsLint would allow a "folder" sourceType.

like image 709
rupps Avatar asked Jun 16 '19 09:06

rupps


2 Answers

You didn't provide code examples in your question, but I assume you do something like this:

api.js

const api = {
  fetchData() {
    // some code that fetches data
  }
};

core.js

const core = {
  init() {
    api.fetchData();
  }
};

The ESLint rule that causes errors when you lint these JavaScript modules is the no-undef rule.

It checks for variables that are used without having been defined. In the code example core.js above, this would be api, because that is defined in another module, which ESLint doesn't know about.

You don't care about these errors, because in your actual JS bundle used in production, the code from api.js and core.js is concatenated in one bundle, so api will be defined.

So actually api in this example is a global variable.

The no-undef rule allows you to define global variables so that they won't cause errors.

There are two ways to do this:

Using Comments

At the beginning of your core.js module, add this line:

/* global api */

Using the ESLint Config

As explained here – add this to your .eslintrc file:

{
  "globals": {
    "api": "writable"
  }
}

Side Note

As some commenters to your question pointed out, it would probably be better to use import and export statements in the modules, together with a module bundling tool like webpack to create one bundle from your JavaScript modules.

like image 88
Patrick Hund Avatar answered Nov 11 '22 21:11

Patrick Hund


A physical JavaScript file with an import/export statement is a module by the standard. A single .js file without import/export is a script by the standard. What you are trying to do is non-conforming to this, there is no specification in ECMAScript that allows splitting a single script or module across several files. I do get where you are coming from, for example: C# has partial classes that allows you to split a class across multiple files. But trying to replicate this without a standard syntax is not wise. Especially, when import/export can and will do the job for you

For example, with the following assumptions, your main.js can be refactored to,

constants.js // <--- constants
ui.js  // <--- logic to build UI
api.js  // <--- exposing public api
init.js  // <--- setup code before use

// main.js 
// If you name this index.js you can import it as 'src/main' instead of 'src/main/main.js'
import { A,B } from './constants'
import { api } from './api'
import { displayUi } from './ui'
import { init } from './init'

init(A);
displayUi(B);

export { api } // <-- re-expose public api
like image 1
Avin Kavish Avatar answered Nov 11 '22 21:11

Avin Kavish