Git Product home page Git Product logo

nollup's People

Contributors

adamburgess avatar alastaircoote avatar alexsey avatar charlag avatar codewitchbella avatar hanswilw avatar houd1ni avatar jakobrosenberg avatar mike-dax avatar morbidick avatar palmik avatar pepsryuu avatar peter-mouland avatar piotr-cz avatar rixo avatar vesalahd avatar vzaidman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

nollup's Issues

Use server-sent events instead of WebSocket

SSE uses normal HTTP and so:

  • it would be easier to integrate the Nollup middleware into a custom dev server / express app

  • it would be easier to proxy to Nollup's dev server (because proxying WS is complicated)

  • as a bonus I'm found of, browsers have an auto retry on SEE, so you can have a cheap "browser automatically picks server back up, after a server restart"

Very high CPU usage using pnpm

Maybe I've done something wrong but even with the dumbest config ever I feel like I have an error while running nollup in order to get HMR working for my CSS and Javascript.

I always get this output in the terminal whatever config I'm using (tried many, from some other repos, etc). The only way for me to get it working is by using the examples as it from the examples folder of this repo, which calls the cli from a javascript file. When I try to use the nollup -c command, that's when issues are coming by.

> npm run dev

> [email protected] dev /Users/user/Desktop/Rollup
> nollup -c --hot --port 3000

Listening on http://localhost:3000
Compiled in 944ms.
Compiled in 441ms.
^C%

Also the node process in my Activity monitor goes off the roof with at least 300% CPU.

This is my package.json

{
  "name": "test-nollup",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "build": "cross-env NODE_ENV=development nollup -c nollup.config.js -w --hot --content-base build --port 3000 --verbose",
    "dev": "nollup -c --hot --port 3000"
  },
  "dependencies": {
    "normalize.css": "^8.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.8.3",
    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
    "@babel/plugin-transform-runtime": "^7.8.3",
    "@babel/preset-env": "^7.8.3",
    "@babel/runtime": "^7.8.3",
    "@rollup/plugin-commonjs": "^11.0.1",
    "@rollup/plugin-node-resolve": "^7.0.0",
    "@rollup/plugin-replace": "^2.3.0",
    "autoprefixer": "^9.7.4",
    "cross-env": "^6.0.3",
    "eslint-config-standard": "^14.1.0",
    "eslint-plugin-import": "^2.20.0",
    "eslint-plugin-node": "^11.0.0",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-standard": "^4.0.1",
    "node-sass": "^4.13.1",
    "nollup": "^0.10.2",
    "postcss": "^7.0.26",
    "postcss-banner": "^3.0.1",
    "postcss-preset-env": "^6.7.0",
    "rollup": "^1.29.0",
    "rollup-plugin-babel": "^4.3.3",
    "rollup-plugin-banner": "^0.2.1",
    "rollup-plugin-browsersync": "^1.1.0",
    "rollup-plugin-bundle-html": "^0.2.2",
    "rollup-plugin-clear": "^2.0.7",
    "rollup-plugin-dev": "^1.1.1",
    "rollup-plugin-eslint": "^7.0.0",
    "rollup-plugin-hot-css": "^0.0.6",
    "rollup-plugin-postcss": "^2.0.3",
    "rollup-plugin-serve": "^1.0.1",
    "rollup-plugin-terser": "^5.2.0"
  },
  "browserslist": [
    "> 0.5%",
    "last 2 versions",
    "not dead"
  ]
}

and my rollup.config.js

import resolve from '@rollup/plugin-node-resolve'
import replace from '@rollup/plugin-replace'
import commonjs from '@rollup/plugin-commonjs'
import babel from 'rollup-plugin-babel'
import devserver from 'rollup-plugin-dev'
import browsersync from 'rollup-plugin-browsersync'
import postcss from 'rollup-plugin-postcss'
import clear from 'rollup-plugin-clear'
import html from 'rollup-plugin-bundle-html'
import banner from 'rollup-plugin-banner'
import { terser } from 'rollup-plugin-terser'
import { eslint } from 'rollup-plugin-eslint'
import pkg from './package.json'
// import settings from './settings.json'

// Define environment and things
const mode = process.env.NODE_ENV
const watch = process.env.ROLLUP_WATCH
const dev = mode === 'development'
const workdir = dev ? 'build' : 'dist'

// Rollup config
export default {
	input: 'src/main.js',
	output: {
		dir: dev ? 'build' : 'dist',
		entryFileNames: '[name]-[hash].js',
		chunkFileNames: '[name]-[hash].js',
		sourcemap: dev,
		format: 'cjs'
	},

	// Plugins
	plugins: [
		// Clean
		// clear({
		// 	targets: [ workdir ],
		// 	watch: true
		// }),

		// Serve
		// dev && watch && devserver({
		// 	port: 3100,
		// 	dirs: [ workdir ],
		// 	basePath: '/'
		// }),
		// dev && watch && browsersync({
		// 	port: 3000,
		// 	proxy: 'http://localhost:3100',
		// 	open: false,
		// 	notify: false
		// }),

		// PostCSS with SASS/SCSS/Stylus
		// postcss({
		// 	extract: true,
		// 	sourceMap: dev
		// }),

		// Javascript
		// replace({
		// 	'process.browser': true,
		// 	'process.env.NODE_ENV': JSON.stringify(mode)
		// }),
		// resolve({
		// 	browser: true
		// }),
		// commonjs(),
		// eslint({
		// 	exclude: ['**/*.scss', 'node_modules/**']
		// }),
		// babel({
		// 	extensions: ['.js', '.mjs', '.html'],
		// 	exclude: ['node_modules/**'],
		// 	runtimeHelpers: true
		// }),

		// Build
		// html({
		// 	template: 'src/template.html',
		// 	dest: workdir,
		// 	filename: 'index.html'
		// }),
		// !dev && terser({
		// 	module: true,
		// 	output: {
		// 		comments: false
		// 	}
		// }),
		// !dev && banner(`${pkg.name} v${pkg.version}\nBy ${pkg.author.name}\n${pkg.author.url}`)
	]
}

Am I missing something ? ๐Ÿคช

Use cosmiconfig to read config

Some advantages:

This would add support for more ways to configure nollup:

  • a nollup property in package.json
  • a .nolluprc file in JSON or YAML format
  • a .nolluprc.json file
  • a .nolluprc.yaml, .nolluprc.yml, or .nolluprc.js file
  • a nollup.config.js file exporting a JS object

It is widely adapted; used by 3.3m github repositories.

It has a documented order in which it will look for configuration.

Starting from process.cwd() it will look for:

  1. a package.json property
  2. a JSON or YAML, extensionless "rc file"
  3. an "rc file" with the extensions .json, .yaml, .yml, or .js.
  4. a .config.js CommonJS module

This should be backwards compatible with the current implementation where the .nolluprc file has precedence over the nolluprc.js file:

nollup/lib/cli.js

Lines 93 to 97 in 1411a03

if (fs.existsSync('.nolluprc')) {
options = Object.assign({}, options, JSON.parse(fs.readFileSync('.nolluprc')));
} else if (fs.existsSync('.nolluprc.js')) {
options = Object.assign({}, options, require(path.resolve(process.cwd(), './.nolluprc.js')));
}

Is there a specific reason the current implementation loads the configuration synchronously (i.e. using fs.existsSync and fs.readFileSync)?

Could be replaced with

const cosmiconfigResult = require('cosmiconfig').cosmiconfigSync('nollup').search();
if (cosmiconfigResult && cosmiconfigResult.config) {
    options = Object.assign({}, options, cosmiconfigResult.config); 
}

cosmiconfig can be used synchronously as well as asynchronously.

See https://github.com/davidtheclark/cosmiconfig for more information.

Why faster than rollup dev mode?

Hi PrpsRyuu,

This stuff looks quite cool. But I'm a little confused, rollup doesn't do many optimisations in dev mode, too. Why is nollup faster than rollup dev mode?

Support dynamic imports

Using dynamic imports produces following error:

{ SyntaxError: 'import' and 'export' may only appear at the top level (29:2)
    at _class.pp$4.raise (<project>/node_modules/nollup/node_modules/acorn/dist/acorn.js:2825:15)
    at _class.pp$1.parseStatement (<project>/node_modules/nollup/node_modules/acorn/dist/acorn.js:859:18)
    at _class.parseStatement (<project>/node_modules/acorn-dynamic-import/lib/index.js:63:118)
    at _class.pp$1.parseBlock (<project>/node_modules/nollup/node_modules/acorn/dist/acorn.js:1161:23)
    at _class.pp$1.parseStatement (<project>/node_modules/nollup/node_modules/acorn/dist/acorn.js:845:36)
    at _class.parseStatement (<project>/node_modules/acorn-dynamic-import/lib/index.js:63:118)
    at _class.pp$1.parseIfStatement (<project>/node_modules/nollup/node_modules/acorn/dist/acorn.js:990:28)
    at _class.pp$1.parseStatement (<project>/node_modules/nollup/node_modules/acorn/dist/acorn.js:834:33)
    at _class.parseStatement (<project>/node_modules/acorn-dynamic-import/lib/index.js:63:118)
    at _class.pp$1.parseTopLevel (<project>/node_modules/nollup/node_modules/acorn/dist/acorn.js:746:23)
  pos: 924,
  loc: Position { line: 29, column: 2 },
  raisedAt: 930 }
ParseError: src/index.tsx
Error: SyntaxError: 'import' and 'export' may only appear at the top level (29:2)
      import('react-axe')
     ^
    at bundle (<project>/node_modules/nollup/lib/index.js:393:19)
    at process._tickCallback (internal/process/next_tick.js:68:7)

Possibly related to acornjs/acorn#809

HMR : some CommonJS modules are not properly started

I got several errors using React-Color and Material-UI. I find some solutions for MUI styling, but with React-Color no ways :-(

I got a TypeError: _common.ColorWrap is not a function when using any React-Color pickers.

Very hard to debug as you are using eval and I get an infinite loop with 'React Dev Tools'...

The error is line 208 in Twitter.js component of React-Color:

exports.default = (0, _common.ColorWrap)(Twitter);

_common.ColorWrap is undefined.

I use my rollup-react-app template for the test. And I only add a React-Color Twitter component to the App to reproduce the bug.

Screenshot 2020-02-12 at 15 02 32

Support ES6 config

I don't know if there are any limitations preventing this, but it would be great to allow ES6 module imports/exports in rollup.config.js.

Eg:

import plugin from 'rollup-plugin';
export default {};

as opposed to:

const plugin = require('rollup-plugin');
module.exports = {};

I've just started using nollup and I need to rewrite my config so it's compatible.

A nollup API

Hi.

Without really knowing how possible this is, based on how nollup works - is it possible / are there any plans for nollup to expose an API matching Rollup's API?

The reason being is that we're toying with the possiblity of using nollup for development mode in Sapper / Svelte apps to speed up the developer feedback loop, but currently I've not been able to get too far due to the lack of a compatible API.

Thread is here sveltejs/sapper#1207 (comment)

exclude subfolder from nollup watch

I keep my build target folder as a subfolder of the main project. I start nollup from the main project folder, so nollup watches the build target as well which results in constant recompile.

In rollup there is a config

watch: {
    exclude: 'dist'
}

This seems a basic requirement to me. Am I missing something maybe?

Missing shared dependencies across dynamic imports

Bear with me...

If I have 2 dynamic imports in my entry points, and both of them import another module, that itself imports another module... And if only the 2nd dynamic import is actually executed, then the transitive dep module is missing, which results in the following error:

Uncaught (in promise) TypeError: modules[number] is not a function

I've pushed a reproduction case on the bug-shared-dynamic-imports branch of my playground repo of the moment.

To illustrate, here what a simple main.js would look like:

if (false) import('./dyn1.js')
import('./dyn2.js')

Where dyn1.js and dyn2.js would both have this code:

import dep from './dep.js'
console.log(dep)

And dep.js itself would be:

import sub from './sub.js'
export default sub

It's this sub.js module that would be missing from the dyn2.js "chunk". It would be present in dyn1.js, but since it is skipped at runtime... Still missing.

rollup-plugin-json isn't supported

The error comes when I try to import the npm package eddystone-url-encoding:

(node:1988) UnhandledPromiseRejectionWarning: Error: "version" is a required argument.
 --- C:\projects\sample-project\node_modules\eddystone-url-encoding\lib\prefixes.json
 --- C:\projects\sample-project\node_modules\eddystone-url-encoding\lib\decode.js
 --- C:\projects\sample-project\node_modules\eddystone-url-encoding\index.js
 --- C:\projects\sample-project\src\utils\Beacon\Eddystone.ts

I'm assuming that the error is from the json plugin and not because the library is a CommonJS module, but, of course, I could be wrong.

WebSocket connection failed

So close to finally having nollup up and running with HMR! This is my first project where I've attempted to use HMR by the way, so I'm sure there are simple things I'm overlooking.

I'm calling nollup like this: nollup -c --hot

The bundle builds without errors and my app loads. But HMR isn't working and this is in the console:

WebSocket connection to 'ws://__hmr/' failed: Error during WebSocket handshake: Unexpected response code: 200

and the line that's throwing this error:
var ws = new WebSocket('ws://' + window.location.host + '/__hmr');

Any suggestions? Should I be filling something in for --hmr-host?

Thank you!

React fast refresh integration

React has new official way to do HMR called fast refresh

Integration with bundler involves few steps (outlined in this comment)

  1. injecting code into modules to perform hot reload (this is easy using transform hook)
  2. adding babel plugin (again easy)
  3. wrapping module load function with some code (this is currently impossible, I think)

My implementation

CodeWitchBella@f873795

This does do everything that is needed (I think) in rollup plugin except point 3 which is implemented using new hook.

Proposed change

Add new hook nollupModuleWrap which can add code around module.__impl call in lib/index.js (see commit linked above for implementation)

Error: Unknown object type "set iterator"

I have a working setup with rollup and typescript. I just added nollup and changed my dev setup to this

rimraf public && cross-env NODE_ENV=development nollup -c --hot --content-base public

I get this error which I really don't understand.

ParseError: ndex.js
Error: Unknown object type "set iterator"
    at bundle (/workspace/phaser3-rollup-typescript/node_modules/nollup/lib/index.js:508:15)
    at async generateImpl (/workspace/phaser3-rollup-typescript/node_modules/nollup/lib/index.js:693:21)

You may test by running yarn dev command here. I have the repository here:

Circular dependencies

Circular dependencies are not caught as an error and continue in an infinite loop.

examples are failing

For me none of the examples work
I cloned the repo, went into an example folder and did

npm install
npm run start

The compile failed with an error:


> @ start /Users/marko/git/nollup/examples/example-circular
> cross-env NODE_ENV=development node ../../lib/cli.js -c --content-base public --port 9001 --hot

internal/modules/cjs/loader.js:651
    throw err;
    ^

Error: Cannot find module 'express'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:649:15)
    at Function.Module._load (internal/modules/cjs/loader.js:575:25)
    at Module.require (internal/modules/cjs/loader.js:705:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Object.<anonymous> (/Users/marko/git/nollup/lib/cli.js:5:15)
    at Module._compile (internal/modules/cjs/loader.js:799:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
    at Module.load (internal/modules/cjs/loader.js:666:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
    at Function.Module._load (internal/modules/cjs/loader.js:598:3)

After that I tried

nollup -c

which did compile, but the page would give an error in the browser console:

Refused to load the font '<URL>' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.

localhost/:1 Refused to load the image 'http://localhost:8080/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

Am I missing something?

ts example

great work , thank you. here's a working typescript example with the proper file extension resolving and what not, pretty annoying to get right with rollup and babel usually. threw in a random hooks test to see how that went, had to add 'createContext' to the named exports. i wish rollup had a way to disable named imports and always use the default export , maybe it does but i havn't figured out a way to so

https://github.com/jeremy-coleman/nollup-react-refresh-tsx

React hot loading without Babel

We currently use Typescript/Rollup to generate and bundle our code. The typescript target ES is ES2018.

We do not use Babel anywhere in the build pipeline, since typescript is enough. Is it possible to use react-hot-loading with nollup without introducing Babel ?

If it absolutely needs to be, what is the minimal footprint it can have with no effect on build times.

Also, it will be great if we could post an example with Typescript and hot-loading.

UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory

When : I switch from a branch or pull some code and Nollup is running

(node:4268) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, lstat '/.../RollupReactApp/.git/HEAD.lock'
    at Object.lstatSync (fs.js:939:3)
    at FSWatcher.onChange (/.../RollupReactApp/node_modules/nollup/lib/dev-middleware.js:160:20)
    at FSWatcher.emit (events.js:321:20)
    at FSWatcher.<anonymous> (/.../RollupReactApp/node_modules/chokidar/index.js:199:15)
    at FSWatcher._emit (/.../RollupReactApp/node_modules/chokidar/index.js:241:5)
    at FSWatcher.<anonymous> (/.../RollupReactApp/node_modules/chokidar/lib/fsevents-handler.js:210:14)
    at addOrChange (/.../RollupReactApp/node_modules/chokidar/lib/fsevents-handler.js:216:7)
    at /.../RollupReactApp/node_modules/chokidar/lib/fsevents-handler.js:226:39
    at /.../RollupReactApp/node_modules/graceful-fs/graceful-fs.js:57:14
    at FSReqCallback.oncomplete (fs.js:154:23)

Instead it should be silent or display a warning ?
Also why is it listening to .git folder ?

Set an env variable when Nollup is running

From Rollup's docs:

Note: While in watch mode, the ROLLUP_WATCH environment variable will be set to "true" by Rollup's command line interface and can be checked by plugins and other processes.

That would be great to have something similar with Nollup (e.g. NOLLUP or NOLLUP_WATCH).

It would allow to transparently adapt the behavior of a plugin without requiring the user to alter their Rollup config. Or to use workarounds like resolveId instead of resolve.

acorn.Parser.extend is not a function

Hello,

I've just installed nollup 0.7.6 and attempted to run it with a simple nollup -c

My npm output is:

/node_modules/nollup/lib/impl/AcornParser.js:43
let parser = acorn.Parser.extend(ImportMetaPlugin);
                          ^
TypeError: acorn.Parser.extend is not a function
    at Object.<anonymous> (/node_modules/nollup/lib/impl/AcornParser.js:43:27)
    at Module._compile (internal/modules/cjs/loader.js:707:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:718:10)
    at Module.load (internal/modules/cjs/loader.js:605:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:544:12)
    at Function.Module._load (internal/modules/cjs/loader.js:536:3)
    at Module.require (internal/modules/cjs/loader.js:643:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/node_modules/nollup/lib/impl/ImportExportResolver.js:11:19)
    at Module._compile (internal/modules/cjs/loader.js:707:30)

Really looking forward to using this. Any help is much appreciated!

TypeError: Cannot read property 'length' of undefined

When I try to run nollup with the reccommended setup for react-refresh I get this error on one of my modules:

ParseError: Users/ashish/thoughtspot/node_modules/use-http/dist/index.js
TypeError: Cannot read property 'length' of undefined
    at /Users/ashish/thoughtspot/blink-v2/node_modules/nollup/lib/impl/utils.js:72:65
    at Array.forEach (<anonymous>)
    at combineSourceMapChain (/Users/ashish/thoughtspot/blink-v2/node_modules/nollup/lib/impl/utils.js:67:22)
    at Object.transform (/Users/ashish/thoughtspot/blink-v2/node_modules/nollup/lib/impl/PluginLifecycle.js:217:11)
    at async parse (/Users/ashish/thoughtspot/blink-v2/node_modules/nollup/lib/index.js:51:31)
    at async parse (/Users/ashish/thoughtspot/blink-v2/node_modules/nollup/lib/index.js:116:17)

The command fails and does not continue after this, just keeps printing the above error. If I comment the above import out, it fails at some other file.

Require calls in some dependencies don't seem to be modified

I'm attempting to modify your example to work with React + Babel, in anticipation of being able to use HMR.

However I receive TypeError: modules[number] is not a function errors in the browser console upon compilation (the compile task displays the "Compiled in xxxms" message however).

When I add a console.log(number) in the require function nollup creates, it will iterate over the numbers 0, 1 then print object-assign

When inspecting sources I find dependencies of React haven't been transformed:

var _assign = require('object-assign');
var checkPropTypes = require('prop-types/checkPropTypes');

I've linked below a minimum viable repro:

https://github.com/Mike-Dax/nollup/tree/react-error

Typescript plugins don't seem to transpile using the start command

I can't seem to get typescript to work. I've tried both these plugins:

https://github.com/rollup/rollup-plugin-typescript
https://github.com/ezolenko/rollup-plugin-typescript2/

Neither appear to transpile the code.

SyntaxError: Unexpected token (6:5)
    type thing = number
        ^
Trace: Error trace
    at bundle (/Users/michaelorenstein/Projects/nollup/lib/index.js:496:17)
    at process._tickCallback (internal/process/next_tick.js:68:7)
    at Function.Module.runMain (internal/modules/cjs/loader.js:745:11)
    at startup (internal/bootstrap/node.js:279:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:696:3)

Building them manually with my usual config, and with the build script provided both work.

It's just the 'start' command that seems to have issues.

I've branched off as far as I got:

https://github.com/Mike-Dax/nollup/tree/typescript-example/examples/typescript-react

Thank you for your help.

Circular Dependencies and Live Bindings

Nollup at the moment does not support circular dependencies.

Webpack supports circular dependencies by implementing the "live binding" specification of ES Modules. It accomplishes this by replacing all import variables with an object, and accessing a special property on the object with a getter that gets the latest value.

// In the exported file, if we exported a variable called "number",
// it will add this to the exports instead of "number" directly.
Object.defineProperty(__webpack_exports__, "a", {
    configurable: false,
    enumerable: true,
    get: () => number
});

// Import variables are replaced to this renamed variable.
var __WEBPACK_IMPORTED_MODULE_0__a__ = __webpack_require__(0);

// All references to the imported variable must be replaced and does a get
// on the specially defined property. This property will return the latest value.
console.log(__WEBPACK_IMPORTED_MODULE_0__a__["a" /* number */]); 

I don't really want to implement this because of the following reasons:

  • Significant complexity, would have to traverse the entire syntax tree, figured out if the imported variable was used, and replace it with the objects. This can introduce a significant performance penalty, and might not be entirely reliable unless all possibilities have been considered (eg. what if a local variable by the same name as an import is declared?)

  • Breaks debugging symbols. By swapping out import variables with objects, it breaks debugging because the variables you see in the code are not the variables that are outputted. So if you want to watch variables, or test stuff in the console, you have to use the transpiled variable name instead which can be confusing.

  • Live bindings is a rarely used feature. Should the live-binding specification be supported for a rare circular use case, and in those situations where it is a use case, is usually a code smell and can be refactored to not be circular? Should performance and debugging be hit where other workarounds may exist?

Would love to hear people's thoughts on this. I have no plans to implement this feature, but it is open to anyone who wants to try solve it.

Ignore falsy plugins as per rollup documentation

Rollup is explicit about ignoring falsy plugins:

See Using plugins for more information on how to use plugins and Plugins on how to write your own (try it out, it's not as difficult as it may sound and very much extends what you can do with Rollup). For plugins imported from packages, remember to call the imported plugin function (i.e. commonjs(), not just commonjs). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins.

(see https://rollupjs.org/guide/en/#plugins)

I quickly tried nollup on our project now, and noticed that it stumbled over such a situation. A quick patch as below made it go further, but then gets stuck on other, more problematic uses in our setup.

As this is only lightly tested: Not a PR, but a starting point of a patch instead:

diff --git a/lib/cli.js b/lib/cli.js
old mode 100644
new mode 100755
diff --git a/lib/impl/NollupContext.js b/lib/impl/NollupContext.js
index f755836..d989aa7 100644
--- a/lib/impl/NollupContext.js
+++ b/lib/impl/NollupContext.js
@@ -39,6 +39,8 @@ module.exports = {
     create: function (options) {
         if (!options.plugins) {
             options.plugins = [];
+        } else {
+            options.plugins = options.plugins.filter(plugin => Boolean(plugin));
         }
 
         if (!options.output) {

nollup keep compiling over and over

Hi, I just tried using nollup (0.11.1) in my project but when I run nollup -c with a rollup.config.js that works and the following .nolluprc.js

module.exports = {
  hot: true,
  contentBase: './public'
};

I get the following output :

$ nollup -c
Listening on http://localhost:8080
LiveReload enabled
Compiled in 3551ms.
Compiled in 150ms.
Compiled in 90ms.
Compiled in 108ms.
Compiled in 69ms.
Compiled in 86ms.
Compiled in 78ms.
Compiled in 69ms.
Compiled in 71ms.
Compiled in 66ms.
Compiled in 70ms.
....

and the list goes on. even if I do not do any editing

Any idea?

syntheticNamedExports

Rollup just released new option for plugins named syntheticDefaultExports. It allows for better implementation of commonjs plugin without need to manually specify named exports which I found to be the biggest obstacle to using rollup.

Link to rollup PR: rollup/rollup#3295

Creating this issue only to bring this option to your attention. Thanks for awesome project.

Change events don't seem to fire on my OS

I'm assuming this is an issue of raw chokidar events being different across platforms. I'm running MacOS High Sierra, 10.13.6.

When I inspect the type, the string provided is 'modified' instead of 'change', and the details contains 'path' instead of 'changedPath'.

I've created a PR that uses the normalised add and change events instead if that's an acceptable fix.

Report compile error to the client

Aaaah, I'm too excited about this!

I've look at how Webpack Dev Server does it: https://github.com/webpack/webpack-dev-server/blob/master/lib/Server.js#L178. They use a compiler hook and write errors on the WS as 'error' event. Apparently, the WS client then publishes this with a custom event on window, for consumption by "plugins". In those, I bet there is the one implementing the module.hot protocol. On the other hand, the WS client does process the compile error & implement the overlay itself.

I'm not a fan of how this is hard to track...

So! I couldn't resist to see how my Svelte HMR would look with compile error reporting, so I spun a test implementation around your idea of module.hot.compile: master...rixo:compile-error-reporting

And here's the code using it: https://github.com/rixo/rollup-plugin-svelte-hmr/blob/master/index.js#L77 (and the demo, if you're into Svelty things -- I hooked it up to my fork for now).

(It looks very well! That's just some very very preliminary very early impression but the whole thing seems flawless... On the paper, it might be better than React Fast Refresh. LOL. Svelte's awesome.)

Anyway, to us... As you can see, I didn't do module.hot.compile but window.__hot.addErrorHandler. That's because I realized that when we get a compile error, it can't be targeted at one module, the whole bundle has to be dead, right?

Were you thinking of propagating the bundle error to all module instances (i.e. call every module.compile callback)?

If so, this way would be very impractical to manage something like an error overlay. We only want to control it from a central location that does not get affected by code reload. We want it central because it has to manage singleton assets, e.g. its overlay's DOM element. Like the WS itself needs to be central to manage its connection.

The questions I've asked myself when doing this:

  • Starting from the WS message that is written by the server: should it contains errors or only allow for one single error? Is it possible to somehow have multiple compile errors simultaneously?

  • Should the server (or the WS client) emit null when the compile error is cleared (i.e. on successful compile)? That makes consumer implementation more straightforward, at least.

Also, if we agree that the addErrorHandler API should be central rather than on module, how to expose it to consumer? I guess window.__hot is supposed to be private? Maybe pass it to nollupBundleInit? That's more restricting but it might be cleaner. That would make nollupBundleInit callbacks the only possible place you have to search to find HMR/WS client related code in plugins.

Ah! And just to mention it, what would be the final touch for error reporting would be that the server manages to deliver something anyway when it starts with an initial compile error. Maybe send a blank script with just the HMR clients (nollupBundleInit). This way we could display the initial error in the browser, like WDS (it does a full reload when the error is fixed). Don't know how doable that would be. But that would really be the icing on the cherry anyway.

So, what do you think?

Global files aren't handled correctly

We have a couple of libraries linked as globals because Rollup hates them. Specifically, the AWS JS sdk stuff.

My rollup.config.js has them as:

globals: {
  'aws-wrapper': 'awsWrapper',
  'AWS': 'AWS',
},

Nollup assumes that import Cognito from 'aws-wrapper'; means to import from a file named aws-wrapper.js in the current directory. This is incorrect and all references to Cognito should be replaced with awsWrapper.default.

Make public directory location configurable

I'm sorry to keep bugging you with all my issues, but I'd really like to bring Nollup to feature parity with Rollup, at least for the official Svelte template and simple cases, and make it the preferred solution for Svelte HMR. I just love Nollup's speed. Sometimes, I wonder if an update has applied because it happened in the time interval while my eyes were jumping from the left side of my screen to the right (editor -> browser)...

So, I've got a problem in my template because I haven't enough control (or maybe understanding) on the URL of the files generated by the bundling.

This problem is the reason why I have this special handling of output.file for Nollup. Note that this workaround doesn't work anymore with 0.9.0.

Say I have output.file: 'public/build/bundle.js'.

In versions before 0.9.0, Nollup will use the full path as URL, e.g. http://localhost:8080/public/build/bundle.js.

In 0.9.0, it only uses the basename, e.g. http://localhost:8080/bundle.js.

What I really want is http://localhost:8080/build/bundle.js. That's what I get if I build this with Rollup and launch a http server from the public directory. The file gets written in public/build/bundle.js, and the server sees build/bundle.js as the URL.

So I would expect Nollup with contentBase: 'public' to produce the same URL.

For illustration, I've hacked something that works for me.

I think reusing contentBase is the correct behaviour because, like I said, that's what you get if you use Rollup + a web server. So Nollup, to align with Rollup, would write the "virtual" (in-memory) file to public/build/bundle.js; and, if it serves (contentBase) from dir public, then it should see the URL as build/bundle.js. Is this a good idea to change the meaning of an existing variable though?

Another question is: what to do with files that are written outside of the public directory? For example, if I have output.file: 'dist/bundle.js', but contentBase: 'public'. Hmm. In this case, my implementation just use the full path of the file as URL, because I don't see any other solution.

With output.dir, I think Nollup's behaviour is aligned with Rollup, as a bundler. However, as server, it makes the assumption that the output dir is also the public dir, which might not hold in every project. I guess most cases can be handled by tweaking entryFileNames, but I think that these settings should live in Nollup's config, not Rollup's. They are related to serving, not bundling.

I'm not too sure what the solution should look like. Should it be based on contentBase or some new specific options?

Does not support import.meta.ROLLUP_FILE_URL_referenceId

With following plugin:

const fs = require('fs')
const { promisify } = require('util')
const path = require('path')

function url({ exts = ['.svg', '.png', '.jpg', '.gif'] } = {}) {
  return {
    name: 'rollup-plugin-custom-url',
    async load(id) {
      if (exts.some(ext => id.endsWith(ext))) {
        const ref = this.emitFile({
          type: 'asset',
          source: await promisify(fs.readFile)(id, { encoding: 'binary' }),
          name: path.basename(id),
        })
        return 'export default import.meta.ROLLUP_FILE_URL_' + ref
      }
      return null
    },
  }
}

And code importing for example .png file:

import url from './logo.svg'
const el = document.createElement('img')
el.src = url
document.body.appendChild(el)

I get following error

{ SyntaxError: Unexpected token (1:21)
    at Parser.pp$4.raise (<project>/node_modules/acorn/dist/acorn.js:2836:15)
    at Parser.pp.unexpected (<project>/node_modules/acorn/dist/acorn.js:689:10)
    at Parser.pp$3.parseExprImport (<project>/node_modules/acorn/dist/acorn.js:2271:12)
    at Parser.pp$3.parseExprAtom (<project>/node_modules/acorn/dist/acorn.js:2254:21)
    at Parser.pp$3.parseExprSubscripts (<project>/node_modules/acorn/dist/acorn.js:2089:21)
    at Parser.pp$3.parseMaybeUnary (<project>/node_modules/acorn/dist/acorn.js:2066:19)
    at Parser.pp$3.parseExprOps (<project>/node_modules/acorn/dist/acorn.js:2010:21)
    at Parser.pp$3.parseMaybeConditional (<project>/node_modules/acorn/dist/acorn.js:1993:21)
    at Parser.pp$3.parseMaybeAssign (<project>/node_modules/acorn/dist/acorn.js:1968:21)
    at Parser.pp$1.parseExport (<project>/node_modules/acorn/dist/acorn.js:1431:33) pos: 21, loc: Position { line: 1, column: 21 }, raisedAt: 22 }
ParseError: src/img/logo.svg
Error: SyntaxError: Unexpected token (1:21)
    export default import.meta.ROLLUP_FILE_URL_logo_svg
                        ^
    at parse (<project>/node_modules/nollup/lib/index.js:93:23)

This was mostly experiment in writing simple replacement for rollup-plugin-url

Output dir, public dir, and URLs

So, this is a bit of a follow up to #56.

I am encountering issues with URLs in several projects I'm trying to Nollupize. I've identified 3 causes:

  • the directories in output.dir are discarded from URL, which defers from Rollup
  • entry / chunk files with same basename overwrite each others
  • in some cases, I need to have a separate dist and public folder, and I need URLs from Nollup to be adjusted accordingly

I've created a repo to illustrate and help diagnostic the issues: https://github.com/rixo/nollup-test-case-output-dir

The problems are described in detail in the readme.

I've gone fancy and used a test runner that is not yet very stable, especially with Windows... Let me know if it doesn't work for you, I'll try to simplify the setup.

Additional options to allow piloting by a test driver

Hi! I'm trying to implement Svelte HMR over nollup. Initial trial went way over expectations. (Initial tests with 3 lines of code suggest it might be one bazillion times faster than Webpack, but it's too early to tell.)

So now I'd want to integrate the nollup setting to my HMR test suite, that only supports Webpack for now. (The meat of the Webpack integration is in a sub project.)

For that, the test harness needs some special programmatic control over the dev server that I believe is not entirely possible currently with nollup. What is needed specifically is:

  1. to control a virtual input filesystem (to be able to generate test source files in memory)

  2. to control / mock the file watcher

  3. to know, on the server side, when bundling is complete / dev server ready (for the initial page load)

  4. to know when a HMR update has completed on the client side (in order to run the assertions only when it's ready)

  5. and also on the client side, after initial page load to know when the HMR client is ready (~WS connected) -- I don't really know how important this is with nollup, but it caused race conditions in the tests with Webpack

Point 4 can already be done by monitoring [HMR] messages in the console.

For point 5 however, there's no initial console message in nollup, which would be great to completely eliminate possibilities of race. For example, a greeting message here would do the trick nicely.

Point 3 can probably be done in a rollup plugin.

However, for the first 2 points, I see no ways to hook into nollup currently. I have experimented with passing as options the chokidar and fs objects that are used here and here, and it seems to do the trick. That's quite fragile because it tightly couples the test driver to nollup's internals but, given the use case, that could be good enough for me. The rest can be done via rollup plugin, I think.

So I wanted to know what you think about this. Can you suggest better solutions, maybe? And would be you be interested in adding this kind of support to nollup? I can work on a PR if needed.

Does not call resolveId for entrypoint

Given example from rollup docs

function myExample () {
    return {
      name: 'my-example', // this name will show up in warnings and errors
        resolveId ( source ) {
            if (source === 'virtual-module') {
            return source; // this signals that rollup should not ask other plugins or check the file system to find this id
            }
            return null; // other ids should be handled as usually
        },
        load ( id ) {
            if (id === 'virtual-module') {
            return 'export default "This is virtual!"'; // the source code for "virtual-module"
            }
            return null; // other ids should be handled as usually
        }
    };
}

module.exports = ({
    input: 'virtual-module', // resolved by our plugin
    plugins: [myExample()],
    output: [{
        file: 'bundle.js',
        format: 'esm'
    }]
});

nollup fails because it does not call resolveId for entrypoint

This is low-priority issue because it is really easy to work around but i figured it would be good to report.

Support array configs?

Hi there,

I was trying this out, but it doesn't seem to support configs with arrays as I am receiving this error:

UnhandledPromiseRejectionWarning: Error: Input option not defined

Is there any particular reason we cannot support an array of configs? If not I am happy to do a PR. Thanks.

Feature request: any way to tell from accept handlers whether the update is direct or bubbled?

Use case: Svelte components can include CSS.

<script>
  import { name } from './foo.js'
</script>

<p> I am {name}.<p>

<style>
  p { color: green; }
</style>

When people are fine tuning their CSS, they're likely to trigger a lot of HMR updates and, if I can tell whether this is just a CSS change, I can skip replacing the whole component and get away with just switching a stylesheet in the browser. This is far better because replacing a component always comes with a risk of HMR quirk, while switching a stylesheet is essentially bulletproof...

But I can only do that safely if I'm sure that the HMR update comes from a change to the component file itself. In the example above, if the component's accept handler is run because it has bubbled from ./foo.js, I do have to recreate the component to reflect the change.

Problem: there's no way currently to tell if an accept handler is run because its module has changed or if it is because an HMR update has bubbled from a dependency, is there?

Suggested solution: in my own hot plugin, I'm passing an argument to the accept handlers with the info.

import.meta.hot.accept(({ hasChangedDeps }) => {
  if (!hasChangedDeps && onlyCss) onlyInjectCss()
  ...
})

I absolutely don't recommend the name hasChangedDeps because each time I go back to this code it takes me some time to figure out what it means already. Maybe bubbled would be good? But the general strategy works well.

That being said, any way to tell if the update is direct or bubbled from an accept handler would be ok for my use case.

Sourcemaps are off with Nollup in a Svelte project

Can be seen in my svelte template. On the branch repro-nollup-sourcemaps, I have removed all my hot stuff from the Rollup config to reduce debugging noise.

I have put 2 debugger in a svelte file to clearly illustrate the problem.

Run npm run dev, and the debugger stops on the right mapped lines in the original svelte source.

Run npm run dev:nollup and everything works but the sourcemaps are off.

Both commands serves the app on http://localhost:5000.

For a little background, I have recently produced a Svelte HMR demo with Snowpack that gives instant feedback over HMR in a project that loads 500 Svelte components on the index page. This has revived interest a little for Svelte HMR in the community. I had the idea to subject Nollup to the same test. Just as fast. Twice faster on full reloads (since Snowpack sends 500+ files to the browser). I'm particularly happy to confirm that Nollup rebuild time is not affected by the size of the project, like the no-bundle dev servers (but unlike Rollup unfortunately). And so all this got me motivated to turn back to Nollup and push it as the preferred HMR solution for Svelte projects. This sourcemap issue has been the main bother for me.

Get changed module information

Hello,

I have my own in process dev server running (in asp.net core) website, it calls out to rollup to process files, and has a rudimentary browser reload based on signalr. I am now looking at adding HMR capability and have been looking at https://github.com/alexisvincent/systemjs-hmr

I have noticed that when calling rollup, it produces a bundle file, but I have no access to information about the "module names" that changed since last time. It seems if I wanted to trigger a reload of a hot module in the browser it would be helpful to atleast establish the module name that changed..

So this lead me to nollup. Could nollup help me here? I.e if I included a nollup plugin in the rollup build, could I collect information about module id's that have been changed? I would need to collect that information, so that my server could send that information to the browser to then trigger the reload of those modules in the browser.

I am pretty new to all this so I am very much just figuring all this out as I go ;-)

Does not work with subscriptions-transport-ws npm package

If I try to build project containing npm package [email protected] it produces following errors:

ParseError: node_modules/subscriptions-transport-ws/dist/client.js
TypeError: Cannot read property 'type' of null
    at walk (/home/isabella/Dokumenty/html/bookcity.live/frontend/node_modules/nollup/lib/impl/ImportExportResolver.js:255:26)
    at process._tickCallback (internal/process/next_tick.js:68:7)
ParseError: node_modules/subscriptions-transport-ws/dist/client.js
TypeError: Cannot read property 'type' of null
    at walk (/home/isabella/Dokumenty/html/bookcity.live/frontend/node_modules/nollup/lib/impl/ImportExportResolver.js:255:26)
    at process._tickCallback (internal/process/next_tick.js:68:7)
    at parse (/home/isabella/Dokumenty/html/bookcity.live/frontend/node_modules/nollup/lib/index.js:93:23)
    at process._tickCallback (internal/process/next_tick.js:68:7)

Offending line in source

It happens on following code

        this.client.onopen = function () { return __awaiter(_this, void 0, void 0, function () {
            var connectionParams, error_1;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(this.status === this.wsImpl.OPEN)) return [3, 4];
                        this.clearMaxConnectTimeout();
                        this.closedByUser = false;
                        this.eventEmitter.emit(this.reconnecting ? 'reconnecting' : 'connecting');
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 3, , 4]);
                        return [4, this.connectionParams()];
                    case 2:
                        connectionParams = _a.sent();
                        this.sendMessage(undefined, message_types_1.default.GQL_CONNECTION_INIT, connectionParams);
                        this.flushUnsentMessagesQueue();
                        return [3, 4];
                    case 3:
                        error_1 = _a.sent();
                        this.sendMessage(undefined, message_types_1.default.GQL_CONNECTION_ERROR, error_1);
                        this.flushUnsentMessagesQueue();
                        return [3, 4];
                    case 4: return [2];
                }
            });
        }); };

Which apparently what tsc generates from this source

Reproduction

git clone [email protected]:CodeWitchBella/nollup-reproduction.git
cd nollup-reproduction
npm ci
npx nollup -c

Reproduction is made as modified examples/example-react-hot-loader from this repo

ParseError: child_process

Hi there,

My bundled file ends up running in an environment that has access to node modules. In one of my modules I have:
let spawn = require('child_process').spawn;

When running nollup -c I get this error:

ParseError: child_process
Error: ENOENT: no such file or directory, open 'child_process'
    at parse (/node_modules/nollup/lib/index.js:93:23)
    at process.internalTickCallback (internal/process/next_tick.js:77:7)

I've tried setting preferBuiltins to both true and false in the node resolve plugin options, but neither works.

Is this something that can be fixed?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.