Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dvlp

Package Overview
Dependencies
Maintainers
1
Versions
232
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dvlp

A no-nonsense dev server toolkit to help you develop quickly and easily for the web

  • 2.0.0-beta-4
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
592
increased by146.67%
Maintainers
1
Weekly downloads
 
Created
Source

NPM Version Build Status

💥 dvlp

dvlp is a no-configuration, no-conditionals, no-middleware, no-nonsense (no-vowels!) dev server toolkit to help you develop quickly and easily for the web. You shouldn't have to jump through hoops to get a development environment up and running, and you definitely shouldn't have to include development-only stuff in your high-quality production code! dvlp is full of hacks so your code doesn't have to be!

Motivation

Back in the good old days, our web development workflow went something like this: write HTML/CSS/JS, refresh browser, repeat. Years later, with the help of Node.js and emerging standards, we started pre-processing our CSS and transpiling our JS to take advantage of more expressive, agreeable language features. At the same time, as writing code became easier and more enjoyable, we began bundling and packaging our (growing amount of) code for delivery to the browser. The modern web development workflow soon looked like this: write HTML/JSX/SCSS/LESS/CSS/TS/JS, transpile, compile, bundle, (hot) reload, repeat. For those of us ambitious enough to tackle a full-stack, universal JS application, you would also need to include a well timed server restart (somewhere) in there.

Today, history's pendulum is starting to swing back the other way. Thanks to JS modules and excellent Node.js/browser support for new language features, it's time for a simpler, more comfortable workflow. Bundling should be treated as a production optimization (like minification), and our application web servers shouldn't be responsible for building our development assets.

Less setup, less complexity, and less waiting is surely the path to developer happiness and comfort.

Philosophy

  • No bundling: write JS modules and load them directly in the browser
  • No middleware: write application servers without special dev/build/bundle middleware
  • No waiting: restart application servers in the blink of an eye
  • No refreshing: automatically reload browsers on file change

How it works

dvlp allows you to easily serve files from one or more project directories (static mode), or from your custom application server (app mode). In both cases, dvlp automatically injects the necessary reload script into HTML responses to enable reloading, watches all files for changes, restarts the app server if necessary, and reloads all connected browsers.

In addition, when working with JS modules, dvlp will ensure that so-called bare imports (which are not supported by browsers) work by re-writing all import paths to valid urls. Since most node_modules packages are still published as CommonJS modules, each bare import is also bundled and converted to an ESM module using Rollup.js. These bundles are versioned and cached for efficient reuse in the .dvlp directory under the project root.

Bonus!

dvlp also includes a simple testServer for handling various network request scenarios during testing.

Installation

Install globally or locally in your project with npm/yarn:

$ npm install dvlp

Usage

$ dvlp --help

Usage: dvlp [options] [path...]

  Start a development server, restarting and reloading connected browsers on file changes.
  Serves static files from one or more "path" directories, or a custom application
  server if "path" is a single file.

  Options:

    -p, --port <port>           port number
    -m, --mock <path>           path to mock files (directory, file, glob pattern)
    -t, --transpiler <path>     path to optional transpiler file
    -r, --rollup-config <path>  path to optional Rollup.js config file
    --no-reload                 disable reloading connected browsers on file change
    -v, --version               output the version number
    -h, --help                  output usage information

Add a script to your package.json scripts:

{
  "scripts": {
    "dev": "dvlp --port 8000 src/app.js"
  }
}

...and launch:

$ npm run dev

Transpiling

In some cases you may want to write HTML/CSS/JS in a non-standard, higher-order language like SASS (for CSS), or JSX (for JS). In these cases, you can pass dvlp a transpile function to convert file contents on the fly when requested by the browser.

The transpile function should accept a filepath and return a content string (or Promise resolving to a string) if the file has be transpiled. If nothing is returned, dvlp will handle the file normally:

// scripts/transpile.js
const sass = require('sass');
const RE_SASS = /\.s[ac]ss$/;

module.exports = function transpile(filepath) {
  if (RE_SASS.test(filepath)) {
    return sass.renderSync({ file: filepath }).css;
  }
};

...reference the original file as you normally would:

<link rel="stylesheet" href="src/index.sass">

...and pass the transpile file with the -t, --transpiler flag:

{
  "scripts": {
    "dev": "dvlp --transpiler scripts/transpile.js --port 8000 src/app.js"
  }
}

In order to keep things snappy, dvlp will cache transpiled content and only re-transpile single files when the original contents have changed.

Mocking

When developing locally, it's often useful to mock requests made from your application server, especially when working with an external API. dvlp lets you quickly and easily mock endpoints by intercepting requests that match those registered with the -m, --mock flag.

Mock a request by creating a .json file describing the mocked request/response:

{
  "request": {
    "url": "http://www.someapi.com/v1/id/101010",
    "ignoreSearch": true
  },
  "response": {
    "headers": {
      "x-custom": "custom header"
    },
    "body": {
      "user": {
        "name": "Nancy",
        "id": "101010"
      }
    }
  }
}

(Note that setting request.ignoreSearch = true will ignore query parameters when matching an incoming request with the mocked response)

Though JSON responses are probably the most common, it's also possible to mock other types of payloads by linking the response.body to an external file:

{
  "request": {
    "url": "http://www.someplace.com/images/avatar.jpg"
  },
  "response": {
    "body": "../assets/avatar.jpg"
  }
}

(Note that the file paths referenced in response.body are relative to the mock file, not the web/project root)

Register mocked responses with the command-line flag -m, --mock and a path to your mock files:

{
  "scripts": {
    "dev": "dvlp --mock path/to/mock/files --port 8000 src/app.js"
  }
}

Your path/to/mock/files could be one of the following:

  • path to directory of files: path/to/mock/directory
  • path to file: path/to/mock.json

(Note that the following require wrapping in "")

  • globbed path to multiple files/directories: "path/to/mock/{api,assets}"
  • multiple files/directories separated by space, ,, :, or ;: "path/to/mock1.json, path/to/mock2.json"

Bundling

As mentioned in How it works, dvlp will bundle CommonJS packages imported from node_modules in order to convert them to es6 modules. Rollup.js is used to create these bundles, and they are then cached on disk inside the .dvlp directory under your project root.

In the rare case you need to configure Rollup.js to work with the packages you're importing, you can pass a custom configuration file:

{
  "scripts": {
    "dev": "dvlp --rollup-config rollup.config.js --port 8000 src/app.js"
  }
}

dvlp will override/ignore the input, treeshake, and watch input options, as well as the file, format, and sourcemap output options. Here is the default configuration currently used:

{
  input: 'path/to/temp/file',
  treeshake: false,
  output: {
    file: 'path/to/cache/file',
    format: 'es',
    sourcemap: false
  },
  plugins: [
    resolve({
      browser: true
    }),
    json(),
    commonjs({
      sourceMap: false
    })
  ]
}

All supported options are listed in the Rollup.js documentation.

Debugging

dvlp uses the debug.js debugging utility internally. Set the following environment variable before running to see detailed debug messages:

$ DEBUG=dvlp* npm run dev

Experimental

  • Run file watcher in separate process: launch with CHILD_WATCHER=true to run file watching operations in a separate background process (default is false)
  • Bundle modules in multiple, separate processes: launch with BUNDLE_WORKERS=n (where n is number of background processes) to run module bundling operations in separate background processes (default is 0)

JS API

server(filepath: string|[string], [options]): Promise<{ destroy: () => void }>

Serve files at filepath, starting static file server if one or more directories, or app server if a single file.

options include:

  • port: number: port to expose on localhost. Will use process.env.PORT if not specified here (default 8080)
  • reload: boolean: enable/disable browser reloading (default true)
  • rollupConfig: string: path to optional Rollup.js config file to configure bundling of bare imports

testServer([options]): Promise<TestServer>

Create a server for handling network requests during testing.

options include:

  • port: number the port to expose on localhost. Will use process.env.PORT if not specified here (default 3333)
  • latency: number the minimum amount of random artificial latency to introduce (in ms) for responses (default 50)
  • webroot: String the subpath from process.cwd() to preppend to relative paths (default '')
const { testServer } = require('dvlp');
const server = await testServer({ port: 8080, latency: 20, webroot: 'lib' });

Returns a TestServer instance with the following properties:

  • latency: number the minimum amount of random artificial latency to introduce (in ms) for responses (default 50)
  • webroot: String the subpath from process.cwd() to preppend to relative paths (default '')
  • loadMockFiles(filepath: string|[string]): void load and register mock response files (see mocking)
{
  "request": {
    "url": "http://www.someapi.com/v1/id/101010"
  },
  "response": {
    "body": {
      "user": {
        "name": "Nancy",
        "id": "101010"
      }
    }
  }
}
server.mock('path/to/mock/101010.json');
const res = await fetch('http://www.someapi.com/v1/id/101010');
console.log(await res.json()); // => { user: { name: "nancy", id: "101010" } }
  • mock(request: string|object, response: object, once: boolean): void add a mock response for request, optionally removing it after first use (see mocking)
server.mock('/api/user/1234', {
  body: {
    id: '1234',
    name: 'bob'
  }
}, true);
const res = await fetch('http://localhost:8080/api/user/1234');
console.log(await res.json()); // => { id: "1234", name: "bob" }
  • destroy(): Promise<void> stop and clean up running server

If unable to resolve a request to a local file, testServer will respond with a dummy file of the appropriate type. This makes it easy to test ServiceWorker pre-caching, for example, without having to correctly resolve paths or create mocks. In addition, testServer supports the following special query parameters:

  • offline simulate an offline state by terminating the request (fetch('http://localhost:3333/foo.js?offline'))
  • error return a 500 server error response (fetch('http://localhost:3333/foo.js?error'))
  • missing return a 404 not found response (fetch('http://localhost:3333/foo.js?missing'))
  • maxage=value configure Cache-Control: public, max-age={value} cache header (fetch('http://localhost:3333/foo.js?maxage=10'))

testServer.disableNetwork(): void

Disable all network requests with origin that is not localhost. Prevents all external network requests for the current Node.js process.

testServer.disableNetwork();
await fetch('https://github.com/popeindustries/dvlp');
// => Error "network connections disabled"

testServer.enableNetwork(): void

Re-enables all previously disabled external network requests for the current Node.js process.

FAQs

Package last updated on 25 Jun 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc