Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parcel 2 RFC #1952

Merged
merged 3 commits into from Oct 15, 2018
Merged

Parcel 2 RFC #1952

merged 3 commits into from Oct 15, 2018

Conversation

jamiebuilds
Copy link
Member

@jamiebuilds jamiebuilds commented Aug 28, 2018

[View Rendered]

This RFC is written as documentation for the project, our documentation should
be detailed enough to work as a spec, and it's easier to write it once this way
than to approve a spec and start again on the documentation from scratch.

Everything in Parcel should be documented here, if it is not documented it will
not be part of Parcel 2.


Please let us know if you have any suggestions by commenting inline on the diff of this draft.

All feedback, from anyone, is welcome.

@JacobMGEvans
Copy link

JacobMGEvans commented Aug 28, 2018

Is there going to be any SASS @ import support coming up? Just curious, it was something I ran into recently had to create a weird workaround. I think it was just so many partials in multiple entry points or something.

Copy link

@johnsonw johnsonw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good level of detail. I left a couple of comments.


## Getting Started

Before we get started, you'll need to install Node and Yarn (or npm) and create

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the minimum node version that is supported?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will always be whatever the lowest active LTS version of Node is.

"name": "my-project",
"scripts": {
"build": "parcel --production",
"start": "parcel --serve"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using a postversion script for production builds.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that is necessary for this guide


#### `--public-url <url>`

[todo]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this implemented yet?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been wanting to discuss this more with @devongovett cause it's sorta the odd flag out in the CLI


#### `--log-level <level>`

Set the log level, either "0" (no output), "1" (errors), "2" (warnings +
Copy link

@johnsonw johnsonw Aug 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would read cleaner to list these out:

Sets the log level (Default 2):

  • 0: No output
  • 1 : Errors
  • 2: Warnings and Errors
  • 3: All


### `package.json`

[todo]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What needs to be added here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dunno, just needs a description


#### `--log-level <level>`

Set the log level, either "0" (no output), "1" (errors), "2" (warnings +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a more detailed log mode? See #1834

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about the difference between verbose and debug

Is it dramatically different from parcel --verbose > parcel.log?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally debug printed a bunch more things like bundler options for example.

With the current implementation it is the same as parcel --verbose > parcel.log except for the timestamp but that's just a slightly more complex command.

I still however think we should have both, but with Debug also having some more data like OS, Node Version, Parcel Version, Options, ... (unless that would be considered part of verbose)
So we instantly have all the information we need if anyone makes an issue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I'd be happy to add another level above verbose, but I would argue that it shouldn't write to a file by default

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, I agree it wasn't the best idea to spam the user with logfiles by default.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered the debug module where you'd use literal names as a combination of filters in the DEBUG envvar to introspect into individual modules and components? Ex., DEBUG=parcel:*.


```json
{
"browser": "distflinesof/browser/index.js"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a typo. Shouldn't it be dist/browser/index.js?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...indeed, wtf happened?

```

See [Aliases](#aliases)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we support externals? #144

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good question, I think we need to talk about it a bit more.

One part of the problem I think belongs in aliases:

"aliases": {
  "react": "https://unpkg.com/react@16.4.2/umd/react.production.min.js"
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, however I'm not sure how that would work in practice as you can't reliably predict what parcel has to replace require('react') or import 'react' with as far as I know.

My main concern is probably that there is not really one standard for how to publish prebuilt packages.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think aliases makes sense as along as you have a configuration for under what global name a package is exported and support packages which have only side effect. Maybe allow aliases to map to an object like this?

"aliases": {
  "react": {
     "url": "https://unpkg.com/react@16.4.2/umd/react.production.min.js",
     "global": "React"
   },
   "datatables": { 
     "url": "//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css",
     "global": null
   }
}

Copy link

@Daniel15 Daniel15 Sep 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mohsen1 That looks great to me. Ideally Parcel could handle falling back to a local module if the external one fails to load, rather than having to manually write the code for that (see my comment in #144 (comment)) but perhaps that's outside the scope of Parcel?

"main": "dist/main/index.js",
"module": "dist/module/index.js",
"browser": "dist/browser/index.js",
"browserslist": ["> 1%", "not dead"],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's already "common" to define "browserslist" as a top level property like this but it creates an inconsistency with the "engines" property. Does it make sense for "browsers" to be just another "engine"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we change what people are already doing they will just end up adding and maintaining both

@lbguilherme
Copy link
Contributor

--target node|browser|electron is not there.

@devongovett
Copy link
Member

@lbguilherme see https://github.com/parcel-bundler/parcel/blob/parcel-2-rfc/PARCEL_2_RFC.md#targets

@azeznassar
Copy link

Could you add the basic CLI commands for getting started in both Yarn and NPM?


## Introduction

Parcel is a compiler for all your code, regardless of the language or toolchain.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"all your code" sounds too broad, consider "all your web application frontend code".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parcel can also be used for back-end code, mainly node

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, then something like "web application frontend and Node.js-based backend code". It isn't so smart to build your Makefile-driven C++ server or a Ruby app, is it? (I'd hope it could, but alas)

P.S. Nevermind Ruby. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd like to keep our options open. :) Perhaps something like react native could be packaged with Parcel. The architecture has nothing JavaScript or even Web specific in it, so it should be possible to extend to any platform.


Configure the hot reloading port.

#### `--[no-]source-maps`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#### `--source-maps`, `--no-source-maps` for searchability by option name and similar to other boolean options.

output. Defaults to `package.json#source`, falling back to `src/index.*` or
`index.*`. See [#Entries](#entries-sources-targets-environment).

#### `--serve, -s`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put the option-separating commas outside of the backticks consistently?

- #### `--serve, -s`
- #### `--open, -o [browser]`
+ #### `--serve`, `-s`
+ #### `--open [browser]`, `-o [browser]`
  #### `--cache <dir>`, `--no-cache`
  #### `--hot`, `--no-hot`

Copy link

@bjankord bjankord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any mention of CSS modules in the Parcel 2 RFC. I'm curious if this is something the team is interested in. There is an open issue around CSS module support in parcel with a proposal for a zero-config option that would be nice to get feedback from the core team on if it is something that can be addressed in parcel 2.

@DeMoorJasper
Copy link
Member

DeMoorJasper commented Aug 29, 2018

@bjankord I think this might be a feature of @parcel/transform-postcss and shouldn't be part of the Parcel 2 Spec as this is specific to postcss and Parcel 2 itself is basically just a wrapper around transforms, packagers, ...

@mmun
Copy link

mmun commented Aug 29, 2018

What is a bundle exactly? Is it just a collection of arbitrary files (i.e. of different asset types)?

@jamiebuilds
Copy link
Member Author

What is a bundle exactly? Is it just a collection of arbitrary files (i.e. of different asset types)?

@mmun Bundles should consist only assets of the same asset type. Although transforms can convert one asset type to another.


There are some rules that should be followed across every type of plugin:

- **Stateless** — Avoid any kind of state, it will likely be the source of bugs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some heavy transformers like FavIcon generator require caching to perform well. Do plugins get first class access to read/write cache managed by Parcel core?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cache will be handled by Parcel, as far as I know transforms won't have direct access to it. But every transform output will be cached.

It's more complex than cache every result but it should be pretty optimised to never have to transform anything unless it changed (based on content hashes of the asset and deps)

yarn add --dev parcel
```

From there you just need to point Parcel at some of your entry files. Like if

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding the getting started commands for NPM as well, the master branch of the README.md has both yarn and NPM. Was it a conscious choice to remove it?

Could do something like this

or with npm:

npm init
npm install -D parcel

@mmun
Copy link

mmun commented Aug 30, 2018

@jamiebuilds Gotcha. How would you model optimizations across bundles? I'm thinking of something like inlining images into CSS.

@jamiebuilds
Copy link
Member Author

I imagine that would be best done in CSS compilers. I believe Sass does that already


## Plugins

### Resolvers
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to confirm a resolver plugin can do what TypeScript module resolution spec describes.


See [Reporters](#reporters)

## Parcel Architecture
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An in-memory FS was discussed before. Will Parcel 2 maintain an in-memory FS? Will plugins get access to that FS?

I'm asking because some tools like GraphQL codegen write .d.ts TypeScript files to disk to make TypeScript happy about types. if the TypeScript compiler uses an in-memory FS and GraphQL writes to that you won't need to write to source directories to make the build pass

- `@parcel/transform-json`
- `@parcel/transform-json5`
- `@parcel/transform-less`
- `@parcel/transform-posthtml`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how can one extend/configure the official transformers, or make use in their own plugins? for example, I want to rewrite some HTML tags with the posthtml transformer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parcel takes in an array of transforms, so they're chained so you can manipulate the output (of the previous transform) as much as you want.

ASTs are being sent from transform to transform, so if it's compatible you can re-use it (for performance).

Not sure why you'd ever wanna extend a transform, you could possibly re-use internals of another transform although that is probably risky as that's usually outside the scope of the transforms public interface and therefore not protected from change in minor releases.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take the example, where I want to rewrite some tags in the html files. I assume parcel will use the ootb posthtml transformer for finding the referenced assets (CSS,JS). so I would just add my own transformer, based on posthtml, or traverse the AST myself? And add this to the transformer chain for HTML via API or config?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no clue what ootb means, but this is how it would probably work.

.parcelrc

{
  "extends": "@parcel/config-default",
  "transforms": {
  	"*.html": ["@parcel/transform-posthtml", "parcel-transform-something"]
  }
}

Parcel will run through it's own stuff collecting deps,... than parcel-transform-something would run in the same thread on the same asset, with the output of the previous transform as it's input. You could traverse the ast to get some custom dependencies and I think you can also modify dependencies.

This is (sort of) how plugins work in posthtml as well, so it should be no different. Everything should be possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great, this is what I would have expected. and of course this is all configurable via API as well, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API will also search for the parcelrc file or default config as far as I know.

It will also take an options object similar to the one parcel uses now but slightly different as you can see some cli flags are different in this RFC.

Not sure if you'll be able to provide a hardcoded parcelrc config.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you'll be able to provide a hardcoded parcelrc config.

We want to use parcel as packager within our CLI tool, and ensure that certain transformers are present. with the 1.x version, we just register the asset types directly via API. so it would be important to be able to do the same for the transformers as well.

something along the lines of:

let tx = bundler.getTransformers('*.html');
tx.push(myCoolTransformer);
bundler.setTransformers('*.html');

(but maybe we should move this discussion into an issue)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to create a new issue, this is one big RFC for parcel 2.
So it's already in the right place.

The API should probably also be documented in this spec.

@mischnic
Copy link
Member

Will there be a standardised way for plugins to have a config inside .parcelrc?

@peanutbother
Copy link
Contributor

Will there be a standardised way for plugins to have a config inside .parcelrc?

I think this would be a counter productive choice since it would clutter up parcel specific configuration, since every tool should bring its own configuration.

Maybe you should add your comment as review / request

@DeMoorJasper
Copy link
Member

@mischnic this is kind of against what we are trying to do as far as I know. parcelrc just contains the plugins as described in this RFC, pretty sure it should not contain any plugin specific config.

You might try to convince otherwise though

@mischnic
Copy link
Member

.parcelrc just contains the plugins as described in this RFC

Generally, I think this is a good decision, the used components and their configurations are cleanly separated (as opposed to the huge webpack config). But having loads of dotfiles (.babelrc, .postcssrc, .browserslistrc, cssnano.config.js, .posthtmlrc, .env, .mypluginrc) isn't a pretty solution either.
Anyway, I'll just use a separate config file.

@peanutbother
Copy link
Contributor

peanutbother commented Oct 2, 2018

@mischnic

[...] But having loads of dotfiles (.babelrc, .postcssrc, .browserslistrc, cssnano.config.js, .posthtmlrc, .env, .mypluginrc) isn't a pretty solution either.

This is generally a failure of file structure concept.
My opinion on this is, that web projects should contain or link to a .config folder which would contain the configuration of project tooling, like parcel, sass, editorconfig, etc
But this generally involves a lot of rewrinting of all these tools since they rely on the root folder of the project.

Maybe that could solve some issue once every project tool would consider such an approach.
But that's something for another thread.

@DeMoorJasper
Copy link
Member

DeMoorJasper commented Oct 2, 2018

@jbreckmckye not sure what you mean, it won't be possible to define anything else than plugins and transforms in parcelrc, it'll work pretty much the same as it does now.
The only difference will be that everything can be swapped out and ordered in a different way.

I'm pretty sure the config file should only be used whenever 2 plugins actually need to address the same filetype. Which is a very niche case anyways.

@parcel-bundler parcel-bundler deleted a comment from jbreckmckye Oct 3, 2018
@devongovett devongovett merged commit d2dc7c9 into master Oct 15, 2018
@devongovett devongovett deleted the parcel-2-rfc branch October 15, 2018 12:35
@devongovett
Copy link
Member

Merged the RFC doc into master. Further comments can continue here, and any changes should be submitted as PRs.

devongovett pushed a commit that referenced this pull request Oct 15, 2018
devongovett pushed a commit that referenced this pull request Oct 15, 2018
@dawsbot
Copy link

dawsbot commented Oct 26, 2018

Is there an estimation or goal of when Parcel 2 will be ready to use? Can't wait!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet