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

Roadmap ideas #300

Closed
3 of 7 tasks
sindresorhus opened this issue Sep 18, 2018 · 53 comments
Closed
3 of 7 tasks

Roadmap ideas #300

sindresorhus opened this issue Sep 18, 2018 · 53 comments

Comments

@sindresorhus
Copy link
Member

sindresorhus commented Sep 18, 2018

Here are the goals for Chalk 3:

  • Drop support for Node.js 4
  • Bundle all dependencies at publish-time. I would usually never do this, but Chalk is one of the most popular packages on npm. We could use Browserify or Webpack something to make it a single file.
  • require('chalk/lite') which only includes support for 16-bit. For when you need something fast and simple for logging.
  • Move to class-based construction: Move to class-based construction #188
  • Improve speed, both require speed (Improve require speed #180) and execution speed (Improve runtime performance #333).
    For execution speed we could add fast-paths for when only using 16 colors, which is the most common use-case.
  • Stop using the color-convert module. It's too slow and flexible. We don't really need that many ways of specifying colors. I would prefer to support just keywords, HEX, RGB. I'm honestly not sure if this is feasible. Just an idea for improving the package size and performance. Alternatively, make color-convert tree-shakable, so we only get the parts we actually need.
  • Browser DevTools support built-in? This has been a common request and as long as it doesn't require too much code (and no new dependencies), I welcome a PR adding it.

We welcome contributions to help with this effort and ideas for the v3 goals. 🙌


@Qix- Thoughts? Anything else?

@Qix-
Copy link
Member

Qix- commented Sep 18, 2018

We could use Browserify or Webpack something to make it a single file.

Out of Webpack, Browserify, Parcel and Rollup, my vote is Rollup. It's quick and very easy to get working exactly how you want it, and hasn't given me any headaches yet.

Plus it has treeshaking support.

I'm open to someone rewriting Chalk in TypeScript

As long as TypeScript can do things simply and efficiently, I'm not strictly opposed. I still would prefer to see Chalk remain in ES6 out of principle but the poor Typescript community has had a heck of a time with those type definitions.

I would, however, like to see a clear idea of how the new Chalk would work API-wise for both Typescript users as well as ye olde Javascript users:

  • would the interface and its usage remain the same?
  • can it help the fact that new instances of chalk currently have to be constructed in a weird way to get template tag support to work?

Improve speed, both require speed (#180) and execution speed.

@sindresorhus / community - what profiling tools are standard now? I wish there was something that could visualize flame graphs (maybe Addy Osmani knows something about this) - but in my albeit quick and limited research I couldn't find anything.

Having a really strong handle as to what is slowing us down would be beneficial.

For execution speed we could add fast-paths for when only using 16 colors, which is the most common use-case.

Not sure how much of this is a problem after we bundle everything up. Using ansi-colors will boil down to an object lookup.

Alternatively, make color-convert tree-shakable, so we only get the parts we actually need.

Sure, I'm very much in agreeance - although I need some guidance on this: in order to use tree shaking, you need to use export/import statements, which aren't yet supported by Node. So how do I publish to npm in a way that we can use it with Rollup?

Browser DevTools support built-in? This has been a common request and as long as it doesn't require too much code (and no new dependencies), I welcome a PR adding it.

debug does it, I don't see why not - just a matter of changing the wrapping mechanisms with HTML instead of ANSI codes. Would even pair nice with the existing color-convert support by using CSS strings, too.

@chalk chalk deleted a comment from Qix- Sep 19, 2018
@pspeter3
Copy link

Is anyone owning the TypeScript conversion? I would be happy to help with that and bundling during publish

@Qix-
Copy link
Member

Qix- commented Sep 19, 2018

@pspeter3 go for it - pull requests are always welcomed.

@felixfbecker
Copy link

I dont really understand the benefit of bundling. Why can’t the consumer bundle? If the packages bundle, consumers lose the ability to dedupe, which makes the end bundle larger, not smaller

@jaylinski
Copy link

Another goal could be to reduce the install size: https://packagephobia.now.sh/result?p=chalk

(Although it's already pretty good.)

@styfle
Copy link
Contributor

styfle commented Sep 19, 2018

After looking through chalk and it's dependencies, it will be quite hard to decrease the install size without removing dependencies like ansi-styles.

I found only one package that could use some improvement and submitted a PR: colorjs/color-name#13

There are some similar tools which have zero dependencies:

https://packagephobia.now.sh/result?p=kleur
https://packagephobia.now.sh/result?p=colorette

But as you said, chalk is under 100 kb which is quite good for a npm package.

@Qix-
Copy link
Member

Qix- commented Sep 19, 2018

@jaylinski 90 kilobytes is not a lot. I'm not worried about that, really.

@styfle good catch, thanks for submitting that PR to them.

I'm also on the fence about bundling. I don't see a lot of practical benefits right now since the bundling tech just isn't there. We'd have to supply both an import/export version of the modules (for bundlers) plus a compiled version that worked in Node, effectively doubling the publish size and complexity.

Otherwise we bundle, which has a number of downsides:

  • No vulnerability reports upon install
  • No deprecation reports upon install (and no letting npm automatically select versions for you in the event something gets deprecated)
  • Guaranteed n * m install size were n is the number of different versions of Chalk within a large project (could be many, many times) and m is the number of dependencies Chalk has - as @felixfbecker mentioned

I'm sure there are other downsides that I'm missing but it all feels like a hack and a move backwards.

I'm not convinced either.

@dylang
Copy link

dylang commented Sep 19, 2018

If the string template feature is kept around:

  • Support multi-line colors, such as
chalk`{blue
This is
blue
}`
  • Don't throw errors when encountering unclosed {, such as multiline-JSON strings.
chalk`{
  "foo": "Bar"
}`
  • Exposed the templating feature as a function.
// What we need to do today:
// This hack lets chalk template our strings, like '{blue i am blue}'
const usingChalkTemplates(string) => {
    const array = [string];
    array.raw = [string.replace(/\\/g, '\\\\')];
    try {
        return chalk(array);
    } catch {
        // Chalk throws errors on unclosed {, such as multi-line JSON
    }
    return string;
}

// This would be better:
const usingChalkTemplates(string) => chalk.template(string)

If it is removed for size/maintainability, then I hope it can continue as a separate package. We don't use it much, but when we do it helps large blobs of text with colors, such as --help screens, be easier to read and write.

I also have a logger I'm working on that uses it to support color in the logger without having to import chalk every time you want a little color in a log message.

log.info(`Development server {blue.underline ${hostname}:${port}} is ready.`);

I don't know if this feature of chalk has caught on, but it's been convenient.

@dertieran
Copy link

@sindresorhus / community - what profiling tools are standard now? I wish there was something that could visualize flame graphs (maybe Addy Osmani knows something about this) - but in my albeit quick and limited research I couldn't find anything.

Having a really strong handle as to what is slowing us down would be beneficial.

@Qix- I really like 0x to profile node scripts.

FYI: Running the hello world example from the readme it looks like color-convert/conversions.js is one of the bottlenecks.

@Qix-
Copy link
Member

Qix- commented Sep 19, 2018

@dylang:

Support multi-line colors, such as

That should be supported already. If it isn't, let's make sure to get a bug report submitted.

Don't throw errors when encountering unclosed {, such as multiline-JSON strings.

Those need to be escaped (\{). Again, if that doesn't work a bug report should be submitted.

Exposed the templating feature as a function.

Not as straightforward - one of the problems is that substituted text might have {} in them which will throw off the template engine. It doesn't make a ton of sense not having interpolated values.

In your particular case, perhaps using the logging levels as tags themselves might be a viable solution:

log.info`some info here: ${myMessageText}`;

@dertieran ayy 🎉 that will work, thanks!

I wonder if it's the BFS that occurs with color-convert - I've opened a ticket to perform this BFS at publish time instead of runtime: Qix-/color-convert#56

@callumlocke
Copy link

callumlocke commented Sep 20, 2018

I'm open to someone rewriting Chalk in TypeScript if they also do #188.

Any interest in rewriting it in Flow? Either way it would be good to provide out-of-the-box type definitions for both TypeScript and Flow.

@nyteshade
Copy link

Flow type is far better for debugging purposes, can be stripped of types with Babel and other tools easily enough and still offers all the same typing as you’d get with typescript while adhering to ES6 and JavaScript standards.

@Qix-
Copy link
Member

Qix- commented Sep 21, 2018

@nyteshade

Flow type is far better for debugging purposes

How so?

can be stripped of types with Babel and other tools easily enough

Isn't that what tsc is?

while adhering to ES6 and JavaScript standards.

But neither Flow nor Typescript are ES6 standard. They both require compilation. Either way, we'll have to add a publish step - at which point, it doesn't really matter which is chosen from a release standpoint.

The reason why Typescript is being proposed is because flow types aren't really the issue - typescript types are. Looking through the issues tracker shows a large amount of problems 'defining' chalk for typescript.

Reiterating my point - I'd personally rather bring Chalk into modern times by keeping it highly ES6 out of principle for similar philosophic reasons you stated @nyteshade but I know that might hurt the TS community.

@sindresorhus
Copy link
Member Author

I would, however, like to see a clear idea of how the new Chalk would work API-wise for both Typescript users as well as ye olde Javascript users:

I haven't really spent any time thinking about that yet. Maybe. The main driver for rewriting in TS is that we'll have a build step anyway with bundling, so might just as well rewrite in TS so we don't have to also maintain the TS definition file separately.

So how do I publish to npm in a way that we can use it with Rollup?

https://babeljs.io/blog/2018/06/26/on-consuming-and-publishing-es2015+-packages

I dont really understand the benefit of bundling. Why can’t the consumer bundle? If the packages bundle, consumers lose the ability to dedupe, which makes the end bundle larger, not smaller

The benefit is require speed and less dependencies, so faster installs. Usually, this would not be a problem, but Chalk is just used so much. Chalk is for Node.js. The consumer would never bundle themselves. We don't really loose much on not being able to dedupe as most of our dependencies we have only we use, so they usually won't get deduped anyway.

After looking through chalk and it's dependencies, it will be quite hard to decrease the install size without removing dependencies like ansi-colors.

Note: It's ansi-styles, not ansi-colors.

We'd have to supply both an import/export version of the modules (for bundlers) plus a compiled version that worked in Node, effectively doubling the publish size and complexity.

No, we would only have one compiled version.

@sindresorhus
Copy link
Member Author

Any interest in rewriting it in Flow?

No, I'm used to TypeScript and prefer that.

@felixfbecker
Copy link

Chalk is for Node.js. The consumer would never bundle themselves.

Consumers that are actually impacted by require speed already bundle, e.g. Electron apps like VS Code, or CLIs like yarn. I doubt this impacts the average consumer. If it does, having one of its many dependencies be bundled probably won't have a noticeable impact. Would be nice to see some numbers.

We don't really loose much on not being able to dedupe as most of our dependencies we have only we use, so they usually won't get deduped anyway.

If they are really not used by anyone else, why are they separate packages in the first place?
I would find it concerning if packages start adopting this approach of bundling deps. It's npm's job to resolve dependencies, and only the top-level consumer should bundle. Some other concerns have been mentioned like what if there is a security vulnerability reported, and npm audit won't report it, and nobody has the ability to upgrade through a soft range. What if the top-level consumer bundles, and only uses a fraction of chalk API (and transitive dependencies), but tree shaking cannot kick in because chalk and its deps are already bundled (one might argue that this is a hypothetical example, but this is what gives me an uncomfortable feeling about this).

@wcastand
Copy link

Hello everyone,

i'd like to help, the color-convert seems like something i could work on if no one is already doing it.
Did you choose a solution between the two proposed in the top post (make color-convert tree-shakable or write your own color converting library to handle less case and make it smaller) ?

if you think of something else i could help more, let me know :)

@sindresorhus
Copy link
Member Author

sindresorhus commented Sep 22, 2018

@wcastand Probably best to start with trying to make color-convert tree-shakable. We can have rewriting as a backup plan. We appreciate your help 🙌

@wcastand
Copy link

wcastand commented Sep 22, 2018

@sindresorhus ok, i'll look into it on the color-convert repo then, thank for the quick answer :)

@Qix-
Copy link
Member

Qix- commented Sep 22, 2018

@sindresorhus https://babeljs.io/blog/2018/06/26/on-consuming-and-publishing-es2015+-packages#non-scalable-solutions

That's what I'm concerned about. Users that can't use Chalk out of the box without the use of Babel will be impacted. Further, in order to include the different versions required for different users, we'd have to include multiple versions, which invariably inflates the overall package size to well beyond what it is now.

This has been my gripe with writing code that uses not-yet-implemented proposals for a long time - publishing it is a pain.

I've read most of that article and I don't see any non-babel, scalable solutions. Using ridiculously complex Babel configurations doesn't look like it'd scale and it just adds to the complexity of a 'one trick pony' module such as Chalk.

I like the idea of tree shaking away a lot of color-convert but I'm not sold on the approaches. The community has given several good reasons why bundling would be detrimental.

importexport

@stevemao
Copy link
Contributor

stevemao commented Nov 2, 2018

I'm also not sure about bundling. If perf is an issue for me I would bundle it myself. It's very easy for consumers to cherry-pick which node modules to bundle (I use serverless-webpack)

@sindresorhus sindresorhus pinned this issue Dec 14, 2018
@Berkmann18
Copy link

Berkmann18 commented Dec 21, 2018

Regarding the browser dev tools support, unless there's a better way, doing something like this might be the way to go.
I'm happy to help if needed.

@dlong500
Copy link

dlong500 commented May 5, 2020

@sugoidesune Nothing would stop you from making your own wrapper that could do exactly what you propose. I've made plenty of console wrappers to reduce boilerplate and/or add other capabilities.

@Richienb
Copy link
Contributor

Richienb commented Aug 23, 2020

@sindresorhus

  • Browser DevTools support built-in? This has been a common request and as long as it doesn't require too much code (and no new dependencies), I welcome a PR adding it.

It's already a feature:

console.log("\u001b[34mHello World\u001b[39m") logs "Hello World" in blue

@matamatanot
Copy link

@Richienb
No for IE 11.

ref: facebook/create-react-app#8439

@sindresorhus
Copy link
Member Author

It's already a feature:

PR welcome to mention browser support in the readme. Should link to a source that describes the Chrome support and if there are any other browsers that support it.

@sindresorhus
Copy link
Member Author

No for IE 11.

We don't support IE (nor should anyone), but this is not the place to discuss that.

@fregante
Copy link

fregante commented Nov 11, 2020

  • require('chalk/lite') which only includes support for 16-bit. For when you need something fast and simple for logging.

Yes please, but do it the other way around: the default entry point should be the lite one because that's what most people will use.

  • I would prefer to support just keywords, HEX, RGB

Yes please! color-convert is 46% of chalk and is slow to load. Nobody really needs hsl in the console.

@Qix-
Copy link
Member

Qix- commented Nov 11, 2020

Yes please, but do it the other way around: the default entry point should be the lite one because that's what most people will use.

This literally won't solve anything if color-convert is still a dependency...

Yes please! color-convert is 46% of chalk and is slow to load.

Color convert is 13.1kB on the wire. If this is a serious concern for you, please explain in detail why that is.

Nobody really needs hsl in the console.

[citation needed]

@fregante
Copy link

fregante commented Nov 11, 2020

This literally won't solve anything if color-convert is still a dependency...

Don’t quote me, quote the original post for the “lite” idea

Color convert is 13.1kB on the wire. If this is a serious concern for you, please explain in detail why that is.

  1. Color convert is slow to load and you’re aware of this: https://github.com/Qix-/color-convert/pull/59. Chalk was even changed to load it lazily for this reason.
  2. I like npx so every byte counts since the user feels it almost every time they run a command.

I used rollup on my npx-able tool and the bundle ended up being 1.2MB. By dropping/replacing unnecessary libraries and got the it to 1/4 the size. Also the original 11s run time is now 1.4s.

Every library on its own is “only a few kB,” but then you have to sum them up.

By the look of this post (which, again, isn’t mine) optimizing performance (by also dropping color-convert) is a shared concern.

@fregante
Copy link

fregante commented Nov 11, 2020

Nobody really needs hsl in the console.

[citation needed]

Ok.

# Find direct dependents
❯ npx npm-dependants chalk | tee list | wc -l
    7171

# Download their tarballs (stopped after the first 3500 packages)for dep in $(cat list); do wget $(npm view $dep dist.tarball) & done

# Extract while keeping them in named folders (some were still clobbered, sorry)for t in *.tgz ; do
     bn=$(basename "$t" .tgz)
     mkdir -p "$bn"
     tar xfz "$t" -C "$bn"
  done
 rg chalk.red --count --glob '*.js' | wc -l
    2447 # files, not packages

 rg chalk.bold --count --glob '*.js' | wc -l
    1117

 rg chalk.keyword --count --glob '*.js' | wc -l
      47

 rg chalk.rgb --count --glob '*.js' | wc -l
      25

 rg chalk.hsl --glob '*.js'
debug-utils-1.0.0-alpha.33/package/index.js
46:  comment: chalk.hsl(30, 20, 50),

done-rainbow-0.1.2/package/index.js
20:                chars.push(chalk.hsl(hue, 100, 50)(c));

lumberjack-1.1.2/package/index.js
323:					message = chalk.hsl(match[1], match[2], match[3])(message)

cli-style-0.1.1/package/dist/index.js
23: * hsl - Example: chalk.hsl(32, 100, 50).bold('Orange!')

debug-utils-5.0.0/package/index.js
72:  comment: chalk.hsl(30, 20, 50),

Of these 5, literally one example needs hsl and it's just a "fun" package.

Let me know if you want me to run any other commands on these 3500 packages before I delete them.

@wtgtybhertgeghgtwtg
Copy link

That isn't necessarily the only way people can call it. For example, ink specifically depends on this, but accesses it a little differently.

@fregante
Copy link

Yes, but this is to show that the vast majority does not need it. Every dynamic access like that is done by middleman packages which just relay color-convert like ansi-style does, like chalk does through ansi-style, and so on. And then nobody uses them in the end.

@Qix-
Copy link
Member

Qix- commented Nov 12, 2020

Yep, I was thinking specifically about Ink with my previous comment.

It's up to @sindresorhus. He can decide.

@sindresorhus
Copy link
Member Author

Alright. Let's do this:

  • No chalk/lite.
  • Remove hsl, hsv, hwb, ansi.
  • Remove color-convert as a dependency. Inline the logic to convert HEX/RGB.

Anyone actually needing more, like Ink, can easily use color-covert themselves. We can document this.

Open question: Should we keep ansi265?

@Richienb
Copy link
Contributor

Richienb commented Nov 20, 2020

Should we keep ansi265?

I've never actually had to use ansi256 directly so in my opinion, there's no need to keep it unless there's still a terminal out there that still needs it.

@Qix-
Copy link
Member

Qix- commented Nov 20, 2020

Yes please keep ansi256. The rest sounds fine.

Let's just unify the hex and rgb methods as out of the box both are useful. Keywords won't be missed, and the rest won't be used. Passing color convert values should be okay, though the problem comes with the template parser. As far as I remember, we don't allow putting in substitutions inside of the chalk specifiers in the templates.

const red = chalk.red;
chalk`This is a {${red} red} word.`; // doesn't work I don't think

Not only is this functionality I've personally missed, but it would also make the migration path for those using the strange color methods an easy route for migration.

const chalk = require('chalk');
chalk`{hsl(100,20,20) some text}`;

// becomes

const chalk = require('chalk');
const cc = require('color-convert');
const hsl = (...args) => chalk.rgb(cc.hsl.rgb(...args));
chalk`{${hsl(100,20,20)} some text}`;

cc @vadimdemedes ☝️ Could Ink be able to handle that trivially? Color convert's API is just cc.from_model.to_model(args), so in the the linked case (from #300 (comment)) it'd be just chalk.rgb(cc[model].rgb(args)).

I think this is acceptable.

EDIT: in fact, I propose we take the template syntax a bit further, if we choose to simplify it:

chalk`{100,24,255 rgb syntax}`;
chalk`{#FFA15B hex syntax}`;
chalk`{127 ansi256 syntax}`;
chalk`{blue.bold legacy syntax}`;
chalk`{${fn} functional syntax}`;

As far as I'm aware, the first three above would ultimately result in the template parser dying with an error, which allows us to implement them without breaking anyone other than those using the (now removed) color converters.

Bonus points for those who spot that this would allow themed template literals now, a feature that has been asked about a couple of times.

@Qix-
Copy link
Member

Qix- commented Nov 20, 2020

Further, we should drop upscaling as brought up by #370. I agree, years later, that this choice was probably not optimal. In my defense, we didn't really know how the 256/16m landscape would look when we added support (truecolor had basically just arrived, all of the linux folks thought it'd die immediately).

We should treat the three models individually except for the case of downscaling to a supported level.

@vadimdemedes
Copy link

Of course, Ink has a colorize function that accepts any color string (e.g. rgb(255, 255, 255)), parses and applies the color. I'm pretty sure it can be adapted to any chalk API. I thought about removing hsl, hsv and hwb formats too to simplify things.

@Richienb
Copy link
Contributor

@sindresorhus Do we plan to bundle chalk?

If not, we can close this issue since every other point has been completed.

@fregante

This comment has been minimized.

@fregante fregante mentioned this issue Apr 17, 2021
7 tasks
@fregante
Copy link

@Richienb I think only this is missing, which can be moved to a new issue:

Browser DevTools support built-in? This has been a common request and as long as it doesn't require too much code (and no new dependencies), I welcome a PR adding it.

@Richienb
Copy link
Contributor

@Richienb I think only this is missing, which can be moved to a new issue:

Browser DevTools support built-in? This has been a common request and as long as it doesn't require too much code (and no new dependencies), I welcome a PR adding it.

b31d6fb

@sindresorhus
Copy link
Member Author

Do we plan to bundle chalk?

No, I no longer think it's worth it.

@CEbbinghaus
Copy link

@Richienb I think only this is missing, which can be moved to a new issue:

Browser DevTools support built-in? This has been a common request and as long as it doesn't require too much code (and no new dependencies), I welcome a PR adding it.

b31d6fb

This doesn't seem to be working for me? is there an option in chrome that needs to be toggled?

@CEbbinghaus
Copy link

This doesn't seem to be working for me? is there an option in chrome that needs to be toggled?

After doing some digging I figured out why it wasn't working and submitted Pr #518.

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

No branches or pull requests