Webpack-cli: [NEXT] Declaring Conventions with Intent

Created on 8 Apr 2019  路  18Comments  路  Source: webpack/webpack-cli

Problem

With webpack there's some uncertainty about how well-defined architectures look. From a user perspective it's hard to envision a project structure that works well at scale and also helps new users to get going quickly.

There are several issues with lack of conventions:

  • Where a configuration will be placed
  • What the name of a configuration is
  • What the default entry point is, and why it makes sense for average users
  • What the default output folder is named (and why it is named dist )
  • Which defaults are set and how configuration lookup works

Rotation needed / Change

Where a configuration will be placed

Personal opinion is to enforce users to have a .webpack folder as explained in this post:
https://medium.com/@ev1stensberg/architectural-beams-in-front-end-f85160e3306b
This is because it will hide complexity in user configurations (comment from a webpack member at twitter) and it will allow users to have a cleaner repository/project structure at a root level.

From what I've heard and what I've experienced in the industry it is quite normal to host webpack configurations isolated, for instance in a folder named webpack or in a mono-repository. That is an indication that we are not enforcing the correct patterns, so it would be smart to enforce a .webpack or webpack configuration folder.

Naming configurations

Current situation/convention is having webpack.config.js, webpack.dev.js and webpack.prod.js. In the industry, I've noticed that the common convention is:

webpack.base.js, webpack.prod.js, webpack.hot.js and webpack.dev.js. This makes sense, cause the user will not have a webpack.config.js file when doing large scale applications, but initial users might. I think it would be smart for us to enforce these industry conventions only when their specified environment is suffixed.

For instance:

webpack NODE_ENV="production" would result in a webpack.prod.js configuration to be used, while for development mode, the development configuration will be used. If no environment is used, we fall back to webpack.config.js. The end result of this would be to enforce well defined defaults strictly in production builds while loosely supporting defaults for initial users, which will make both the general user happy and the experienced developer.

Default entry points

Current default entry is ./src/index.js which does kinda make sense but kinda doesn't. The initial user should have index.js as their default as creating a folder might be troublesome. We should support both. For the relative source code folder, src probably is fine, but supporting lib as well might be a better industry convention. (Feedback welcome)

Default output folder

Having dist as a default output repository is something I've not seen from any tool other than webpack. Other languages like ruby and php use public so it should make sense for us to change the default output directory to public so we are better aligned with highly standardized conventions.

Which defaults are used and lookup logic

The new CLI needs the following:

  • Recursive lookup logic following pattern of prod, dev etc..
  • Set defaults if nothing is found on lookup (make a virtual mem/temp file or folder for output)
  • Better defaults on performance, less code in a configuration file, abstract to plugins perhaps or something similar to hide complexity for users

feedback on this is needed & welcome

Discussion Feature Request High Up for planning enhancement inactive

Most helpful comment

Just sharing that with webpack, as there is no real convention, people also can do things like this (giving another real world example of a project I'm working, where webpack has it's own folder).
Screen Shot 2019-04-10 at 11 12 22

Regarding the .webpack option as a configuration folder. I personally think this is the direction we should go.

Why?

Editors (like .vscode) use it, Github is using it .github, on a global level npm is using it to store global modules, StorybookJS is pushing also into . folders.

Yet when I challenge myself, a Contra I see is that such folders are normally used to hide and ignore things. If that is a goal, to make webpack more in the background and invisible than I vote for that.

All 18 comments

Having dist as a default output repository is something I've not seen from any tool other than webpack. Other languages like ruby and php use public so it should make sense for us to change the default output directory to public so we are better aligned with highly standardized conventions.

For all the frontend frameworks/libraries that I've used webpack with use the dist convention as in most cases a public folder is usually present and contains some static assets like the entry index.html, favicon etc.

So IMO dist seems fine to me, atleast for frontend projects.

I disagree. Public has all the things that goes to browser, having two different folders is an anti-pattern because there's not only static things in public, it's a output folder for files and what is sent to the browser.

From the react docs, 馃

https://facebook.github.io/create-react-app/docs/using-the-public-folder#when-to-use-the-public-folder

@evenstensberg I agree that some good conventions must be followed. But webpack is a js bundler and it should be flexible enough to cover various types of standards. Enforcing one without the user's feedback doesn't seem to be a good approach.

On the other hand, if we enforce these practices, then we must keep it configurable & flexible.

Just sharing that with webpack, as there is no real convention, people also can do things like this (giving another real world example of a project I'm working, where webpack has it's own folder).
Screen Shot 2019-04-10 at 11 12 22

Regarding the .webpack option as a configuration folder. I personally think this is the direction we should go.

Why?

Editors (like .vscode) use it, Github is using it .github, on a global level npm is using it to store global modules, StorybookJS is pushing also into . folders.

Yet when I challenge myself, a Contra I see is that such folders are normally used to hide and ignore things. If that is a goal, to make webpack more in the background and invisible than I vote for that.

@sokra might have thoughts after he's back from parental leave

It took me one day (= trial and error) to realize that I cannot ignore webpack.config.js file
I cannot remember any Unix Tools with which when we do not want a config file the CLI still uses it :(
I developed some CLIs in C and C++ for Linux and I am really surprised about webpack-cli behavior:

  1. It is run even with non existing option
    ./node_module/.bin/webpack-cli --xxxxxxxx

  2. It is run with wrong option
    ./node_module/.bin/webpack-cli --output-target--library # correct: --output-library-target

  3. It reads config file even when --config parameter is [ false | null | "" ]

./node_modules/.bin/webpack \
> --config "" \
> --entry ./test/es6/main.js \
> --output ./test/es6/main.bundle.js \
> --module-bind js=babel-loader \
> --mode development

More surprisingly there is a --no-color option that works while the --no-config has the real usability

20190418_134421

And more issue I am seeing ...

I consider speaking in a project that I have not involved in, as being rude.
But seriously I am completely surprised that a world-class tool like webpack does NOT follow well-known

  • techniques like .git directory to hide the complexity
  • conventions like .webpack.conf or .webpackignore or webpack.conf.js
  • UXD rules like good and concise --help option

Please try to find an Unix tool that has this messy --help output
Not to mention that the options are not sorted alphabetically :) for --a**** to --z****

Advanced options:
  --records-input-path       Store compiler state to a json file.       [string]
  --records-output-path      Load compiler state from a json file.      [string]
  --records-path             Store/Load compiler state from/to a json file. This
                             will result in persistent ids of modules and
                             chunks. An absolute path is expected. `recordsPath`
                             is used for `recordsInputPath` and
                             `recordsOutputPath` if they left undefined.[string]
  --define                   Define any free var in the bundle          [string]
  --target                   Environment to build for                   [string]
  --cache                    Cache generated modules and chunks to improve
                             performance for multiple incremental builds.
                      [boolean] [default: It's enabled by default when watching]
  --watch-stdin, --stdin     Stop watching when stdin stream has ended [boolean]
  --watch-aggregate-timeout  Delay the rebuilt after the first change. Value is
                             a time in ms.                              [number]
  --watch-poll               Enable polling mode for watching           [string]
  --hot                      Enables Hot Module Replacement            [boolean]
  --prefetch                 Prefetch this request (Example: --prefetch
                             ./file.js)                                 [string]
  --provide                  Provide these modules as free vars in all modules
                             (Example: --provide jQuery=jquery)         [string]
  --labeled-modules          Enables labeled modules                   [boolean]
  --plugin                   Load this plugin                           [string]
  --bail                     Report the first error as a hard error instead of
                             tolerating it.            [boolean] [default: null]
  --profile                  Capture timing information for each module.
                                                       [boolean] [default: null]

For example instead of mixing examples in the --help option it could have a separate --example option
As an example, here is my own CLI tool for testing ANSI colors with --example option:

$ bline --example
examples:

    # all lines, foreground red:
    ls | bline -a red

    # all lines, foreground red, background green:
    ls | bline -a red:green

    # all lines, foreground is default (NOTE.3), background is green:
    ls | bline -a :green

    # add color-mode, odd lines (foreground) will be in light,italic,red
    ls | bline -o light:red

    # add text-mode, as well
    ls | bline -o light:italic:cross:red

    # combine options are okay:
    ls | bline -a light:green -i red -I 7 -r yellow -R 5-10

    # using hex value, foreground in red
    df | bline -H -a ff00ff

    # hex, foreground green, background red
    df | bline -H -a 00ff00:ff0000

    # hex just background
    df | bline -H -a :ffff00

    # wrong pattern. DO NOT USE
    df | bline -H a red
    df | bline -a ff00ff

Comparing to :

  --prefetch                 Prefetch this request (Example: --prefetch
                             ./file.js)                                 [string]

As a full-time command-line user ( Linux + i3wm ) for years - I can say the webpack-cli is below the standard. If you do no action at this point, it will be harder to do it later on.
I will be glad to help of any kind on any part if needed.

I really thank you @k-five for your honest and constructive opinion! I guess we still have some work to do in order to achieve a good tool but we're working hard!

@sokra might have thoughts after he's back from parental leave

So IMO dist seems fine to me, atleast for frontend projects.

For me too. dist for distribution seem to be very common. public is often used as additional input directory which is copied to dist.

  1. It is run even with non existing option
    ./node_module/.bin/webpack-cli --xxxxxxxx

This is really a huge problem for usability. This was one bigger complain in webpack 1 and afaik we changed this in webpack 2. We disallowed unknown options and introduced the --env option to allow the user to pass custom options.

Personal opinion is to enforce users to have a .webpack folder as explained in this post

Enforcing seem to be a bit hard. For smaller projects a single webpack.config.js seems to be super fine.

But offering additional options seem to be fine.

In my opinion new top-level commands for production and development seem to be nice:

webpack production builds for production: mode = production, reads config file with production in name (i. e. webpack.production.js, webpack.config.js, .webpack/production.js, .webpack/config.js).

similar for webpack development. Maybe shortcuts webpack prod and webpack dev. I won't allow shortcuts for webpack.prod.js as this doesn't bring much benefit and abbrs are usually bad for readablility and new users.


Regarding command line options. An method to automatically convert the webpack option schema into command line arguments would be great. This would enforce consistency and completeness. We could add additional metainfomation to the schema, like category or user level (basic, advanced, expert). All options already have descriptions which can be used for --help.

  1. It is run even with non existing option
    ./node_module/.bin/webpack-cli --xxxxxxxx

This seem to be caused by https://github.com/webpack/webpack-cli/pull/422/commits/d07276e1a217c7165c986bae1379180484d2ea11

@sokra okay dist stays, webpack.[name].config.js is staying.

I'd like to have webpack look for .webpack folder first, then go to root to look for webpack.config.js.

Regarding schema mapping, could we rather do this manually and decide which features to support? Prefer to have the CLI more easy to use, then having the configurations storing more advanced properties. What do you think about that? It will make webpack easier to use

Hi all.
I am not sure if you are using Linux Terminal daily or not but I do. From morning till night. No GUI.
My best guess is that you are using GUI text editors and sometimes opening Terminal using vscode, etc.
If you try to design a CLI then we will end up with something like webpack-cli
Why? Very simple: conways's law

organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations

What do I mean by say this? Well it is easy to see.
CLIs primary purpose is to be used by --options and not config files. In rare cases I can remember that I have used of some kind of config files even with advance usage of curl, wget, xargs, etc.
On the other hand, when I want to use sublime - which I am not using it - or use vim I use a config file. That is the right choice.
And here is the point, as much as we get closer to GUI tools we use a config file and when we get closer to CLI tools we do not use config file.

In my opinion trying to keep both sides perfect:

  • having a very good & organized config file
  • having a very good & organized --options list

make things worse. You should decide to keep one of these. And because you have put a lot effort to the config file maybe removing --options for webpack will not be too bad.

10 days ago I created my first node application which is a CLI and can be used only from Terminal.
Does it have any --options list. No. Why? because it only uses a config file. That is it.
It is a headache to come up with a good design / tool for both fan of config file and meanwhile --options list. Not just to mention the maintenance cost of it!

I am a big fan of using Terminal but prefer not to use / see webpack as a CLI tool. So why are you developing and maintaining a feature in your tool that the target users / audiences do not want to use it?

I wish you could run an A/B test about it :) Hmm ... it is not a webpage but maybe you can run a survey!

I'd like to have webpack look for .webpack folder first, then go to root to look for webpack.config.js.

There is probably something wrong when both exist. Maybe even throw in this case, so the order no longer matters.

Gotcha. Do you think prioritizing and only using the one in .webpack is ok, even though the root webpack.config is present? I've asked feedback from various of people in the industry and they are abstracting webpack into either mono-repos or inside a webpack folder

From our slack:

For the init feature, does it make sense to make this a CRA like thing?
I'm thinking that people could choose to opt out of webpack, but we wrap it around a plugin like > @jantimon has proposed here:
https://github.com/namics/webpack-config-plugins
Whereas we can ask in init:
Do you want to hide your configuration file as a plugin?
And then you can choose to eject through
webpack-cli init eject ?

....

This way, we can help the initial user, and we can hide the complexity. The plugin system is preferably what we need to do to reduce maint burden

This issue had no activity for at least half a year.

It's subject to automatic issue closing if there is no activity in the next 15 days.

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

Was this page helpful?
0 / 5 - 0 ratings