Clarification on using dependencies or devDependencies

I’m looking for clarification on using dependencies or devDependencies. For example, I’m using backbone through npm and I have it under devDependencies. My final build does not require any node environment so I’m wondering what the best convention is for this. It practically doesn’t seem to make much of a difference but it would be great to understand the best case convention.

Author: Fantashit

12 thoughts on “Clarification on using dependencies or devDependencies

  1. I agree with @dschissler that everybody is doing this wrong. A browser app built by webpack has no runtime node dependencies, and thus all frontend dependencies should be listed as devDependencies. The dependencies vs devDependencies naming convention stems historically from node being a server side package manager, which was abused into a frontend package manager, and this is why the fields have names that are counter-intutive when applied to frontend dev, and is why every project ever is getting this wrong. It is as far as I can tell harmless to list frontend dependencies under dependencies, but it is wrong.

    The way I ran into this was
    NODE_ENV=production npm install
    NODE_ENV=production webpack

    which of course failed because none of the devDependencies were downloaded by npm install, as described in the npm install docs. I am exposing NODE_ENV=production to webpack, because React inspects that environment variable, perhaps this is an issue with react, I don’t fully understand.

  2. @dustingetz I’m a bit confused by your response. You say “all frontend dependencies should be listed as devDependencies” but then you said “…none of the devDependencies were downloaded by npm install” when you set NODE_ENV=production. This would seem to be an argument for tracking dependencies in dependencies instead of devDependencies. Could you please clarify?

  3. @dkreft I agree. Everything should just go into dependencies. That way one would not have to worry what NODE_ENV points to when calling npm i.

  4. This conversation states why it works, but leaves one unsure of the reasoning behind it. Webpack projects seem to add a layer of confusion, but we are simply not asking ourselves the right questions: “How will this project be used in production?”, and “Will we run webpack during production?”

    The argument to put most dependencies under dependencies instead of devDependencies can actually go both ways. More commonly I see people start with putting everything in dependencies but should lean towards devDependencies, and figure out how to use it properly. See the two scenarios below.

    Scenario 1: If your project needs to run webpack in the production environment before serving:

    Packages required to build the webpack project are under dependencies, rather than devDependencies. As @dustingetz says, node is historically used as a “server”, but this is actually still be considered true. For webpack (and many react) projects, we are actually using webpack as a build tool, which translates to our project being considered a “source project” waiting to be built. We now also call our project a “build server”.

    In this scenario, our project is no longer considered the “front end app”, but instead “the project that builds the front end app”. Assuming statement above to be reasonable, dependencies are the requirements to build this project and devDependencies will have things that are not related to building, such as unit testing.

    Scenario 2: If our project does not need to run webpack in the production environment, and has a pre-built copy to serve (or require by other projects):

    This scenario is if we do not need to run webpack in production and we only serve the pre-built files in a node server. This means our project will need to ship with our build folder. The webpack and webpack app dependencies can be placed in devDependencies.

    This scenario is also used if we are creating library packages, instead servers. Others will install the project as a package, and require the pre-built files in their project. If one wishes to help develop our package, then they can clone and install with devDependencies to enable webpack building.

    A caveat to this scenario is that for production, one must have already built using webpack in a development environment.

    Summary:

    Webpack projects should be considered build-type projects first, and not production-type projects, unless webpack is used in production. Packages needed during production goes in dependencies, and packages used just to develop the project goes in devDependencies. If our production environment needs to build (run webpack), then those dependencies must reside in dependencies.

    Of course, one can always put everything in dependencies, but if we are looking to publish our project for others to use or require, then this will consequently bloat their projects’ node_modules folder unnecessarily. Scenario 2 should be the way to go: exhaust devDependencies unless it is required otherwise.

    That’s it! That’s all you need to know!

    Whichever scenario you find yourself in, I would love to know if there are any other pitfalls and caveats!

    Supplementary information:

    1. We are generally in scenario 1 if webpack builds to a folder under .gitignore
    2. React’s usage of environment variables, such as the NODE_ENV variable in scenario 1 will generally be correct, as @dkreft points out.
    3. In scenario 2, to rebuild using webpack we must run npm install as NODE_ENV=development (default) rather than NODE_ENV=production. We must define separately the proper NODE_ENV (and other variables) when running webpack depending on whether we are building for production or for development.
    4. Of course, if we just have the project as just a web server that dishes out the already-built webpack project (from elsewhere), then the webpack dependencies don’t belong in either dependencies or devDependencies (they belong nowhere since they’re already packed in the build! 😛). If we develop our webpack / app within the same project as the server, however, then we are effectively in scenario 2 above and need the appropriate devDependencies.
    5. To keep things simple, most projects, typically small or starter web projects will fall under scenario 1, so they can build and serve at the same time during production. As the project scales, one may find themselves splitting up their server and the webpack app into separate commands or even projects, which will require them to be in scenario 2.
    6. If we use webpack to build an app to deploy somewhere, and no other person or project depends on it, then none of this matters.
    7. When developing on your project, one shouldn’t be calling NODE_ENV=production npm install anyway.

    @dustingetz

    A browser app built by webpack has no runtime node dependencies, and thus all frontend dependencies should be listed as devDependencies.

    This quote is true and untrue. A browser app built by webpack has no node dependencies. However, many projects not only serve but also build during production. It is true that this is an unconventional use of the word “build” for node developers (in scenario 1), as building typically refers to doing it before production instead of during. Instead of build and run in separate commands, it’s more like “build-to-run” in one.

    Sorry for the long text, probably should have been a blog post, but I think this deserves an explanation somewhere on the internet!

  5. @pbrn46 In what circumstance does one have to run webpack in production before serving?

    I have a build server that runs webpack and create the bundles, then I copy these distibution files to the server. So at this point in time I do not need to run webpack yet again in prod.

    Who would run webpack in prod at runtime before serving, isn’t that really ineffcient?

    And in my case should everything go under devDependencies? Of course for development I run locally. Is there any impact on the bundles based on what is in dependencies vs devDependencies?

  6. @jrmcdona For your current situation, and as a general recommendation for everyone, move everything into devDependencies until it is actually needed under dependencies.

    Since you are copying your files to a production server, and the project itself doesn’t serve in production, then it is recommended to use devDependencies, even though both will work fine for you.

    Supplemental information

    Webpack in production

    Running webpack in production should actually be a special use case. This is where your package is actually meant for the end user to webpack (implicitly) with your package. The best example would be if you are creating something like the create-react-app (see the underlying react-scripts package’s package.json), where the package actually compiles the user code with webpack, so webpack would be under dependencies for create-react-app. Another example would be if you are making a package that dynamically builds a .js module for the user to import in their project, but requires extra code from the user, before building the final .js. In any case, it still remains a special use case.

    Efficiency

    In terms of efficiency for running webpack in production (as a server), it would only be the first build that takes time, as the outputs of webpack are static files after the build. The files are not rebuilt every time a client sends a request (although this can actually be a way webpack is used for the super-advanced-evil-masterminds). For the lazy people who have their server and build in the same project, the usual setup is on every change they would crash the server, run webpack, and restart the server (for example using express with node-mon or supervisor); although this method is still typically used for development before publishing to another server anyway. It is usually a good idea to keep the server in a separate process/project, as they are really two different things.

    Redistributing your package for others to program or build

    This conversation is actually only applicable if you want to redistribute the project.

    Interestingly enough, if you redistribute your project just for people to build, then you need your webpack and build dependencies (like loaders, babel, sass, etc) should be in dependencies. Your testing package to edit your code will be in devDependencies, since that’s not required to build.

    Now, if you distribute your project with the pre-built files and the only use is for others to import/include your pre-builts, then everything should be in devDependencies.

  7. I think everything that is needed to create the bundle.js belongs in dependencies unless you commit the compiled files into VCS

    At the same time, in my opinion, everything that is bundled into the distribution should not be in dependencies in most scenarios.
    Take a look at the vue.js or react.js package.json for example..

    https://github.com/vuejs/vue/blob/dev/package.json
    https://github.com/facebook/react/blob/master/package.json

    ..they have 0(!) dependencies, only devDependencies. The dev dependencies are a lot of front-end libraries that people tend to reference as ordinary dependencies. However since the distribution is based around a pre-built bundle vue.js/react.js are doing it exactly the right way in my opinion.

    was this thread conclusive?
    i totally feel @dschissler‘s original question and believe that a look at vue/react pretty much gives a clear direction:

    If a bundler is (like webpack) is involved and you distribute a compiled bundle (pretty much always the case in front-end development), then you probably mostly need devDependencies and probably little to no dependencies.

Comments are closed.