fearthecowboy / static-link

Static Linker for NodeJS/Electron apps
1 stars 1 forks source link

Static Linker for NodeJS/Electron Apps

This utility provides a means to statically-link all your dependencies into a single static-filesystem that is patched into node's module loader.

The Big Picture

Node.js has a great packaging system with npm. Deep down, it's pretty darn flexible, and handles an awful lot of situations just perfectly fine.

That being said, sometimes, you want a little less features, and a bit more rigidity:

Features

This static linker performs the following:

Is this better than Webpack (and the like)?

I'd like to think so, but your mileage may very.

I found webpack overly complex to configure, while it does a whole lotta stuff, it was like using a firehose to wash your dishes: yeah, it'll get the job done, but you're probably looking at a sink full of broken bits in the end.

Since this is specifically tailored towards node/electron apps and not the client side, you may find this useful when you're doing non-browser work.

I also wasn't fond of the invasive nature of hunting down require statements and rewriting them.

Getting Started: Quick and simple

To use static linking, in your package.json add:

a reference to the static-link package in your devDependencies

  "devDependencies": {
    "static-link": "*"
  },

a static-link section that contains dependencies -- just like regular dependencies.

  "static-link": {
    "dependencies": {
      "chalk": "*",
      "marked": "*",
      "marked-terminal": "*",
      "yarn": "^1.1.0"
    }
  },

a script to run the linker.

  "scripts": {
    "static-link": "static-link",   // use 'npm run static-link'
    "build" : "tsc && static-link"  // if you use a language with a compiler 
                                    // (like typescript or babel, etc), run 
                                    // static-link after you compile to patch your entrypoints
  },

Then run npm run static-link and it will:

It will skip the package install generation if the static-modules file is created and package.json hasn't changed.

Use static-link --force to do it anyway.

Advanced Options

The static-link section has several options for controlling the process:

...
  "static-link" : {
    "dependencies" : {
      // specify all your static package dependencies here. 
      // Just like regular dependencies, but nested in "static-link"
    },

    "entrypoints" : [
      // specify the entrypoints to your code here. 
      // This will default to anything in "main" or "bin"
      // or without those, the root "index.js" file
    ],

    "loader":     // the filename to copy the static loader code to. defaults to:
      "./dist/static-loader.js", 

    "filesystem": // the filename to create the static modules filesystem. defaults to:
      "./dist/static_modules.fs" 
  }

Things Worth Noting:

   // all integers are six-byte-big-endian values

   // header intformation 
   int dataOffset;            // offset in the file where the data streams are.
   int hashSize;              // number of bytes in the hashString
   byte[hashSize] hashString; // utf-8 encoded string for configuration file hashing

   // the index is a list of file entries. 
   {
     int nameSize;            // the size of the filename. (0 marks the end of the index. -- see 'zero')
     int dataSize;            // the length of the dataStream. 
     byte[nameSize] filename; // utf-8 encoded string for the filename
   }

   int zero;                  // 0 -- indicating the end of the index

   // starting at dataOffset, the data streams are laid out one after another 
   // the loader builds the index in memory and calulates the offset while it loads the index.
   {
     byte[dataSize];          // lather, rinse, repeat for each file.
   }