3.0.4
https://github.com/jost-s/vue-cli3-demo
Node 8.10.0 / npm 6.4.1 / Windows 8.1
.\node_modules\.bin\vue-cli-service build --mode test./dist foldernpm run build./dist folderCreate a build including all files
Create a build omitting additional images and css files.
At first I ran in to this issue because I deployed an app to a test system where the NODE_ENV was set to "test". Building resulted in an incomplete dist folder without images and css files, even though the output said "Building for production...".
After trying different combinations of environment variables and webpack modes, it turns out the problem is two-fold:
NODE_ENV = test, it looks like production mode is used, yet css and image assets are omitted from the build.This issue is related to https://github.com/vuejs/vue-cli/issues/2327
I think this comes down to the problem of your documentation not explaining the different implacts of NODE_ENV & its default modes well enough, because what you are seeing is expected behaviour and works the way it does for a reason.
So I'll try and explain what we want to get across, and maybe you can give feedback how we can word or strcuture this part of the documentation.
Have you read the documentation about environment variables and modes? this one:
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables-and-modes
It has an explicit note about NODE_ENV:
NODE_ENV
If you have a default NODE_ENV in your environment, you should either remove it or explicitly set NODE_ENV when running vue-cli-service commands.
So the immediate solution to your problem is to call your build process with an explicitly set NODE_ENV=production
In the next section about modes it explains in the first paragraph, that NODE_ENV=test is set by the test mode, which is used by vue-cli-service test:unit.
In other words: NODE_ENV=test creates a webpack config that is intended to be used for unit tests, and is optimized for that purpose. Which is why it doesn't process assets in the way you expect: In unit tests, that would be useless thing to do. So this is intended behaviour for NODE_ENV=test
Similarly, NODE_ENV=development creates a webpack confuration intended to be used during development, i.e. it enables HMR, doesn't hash assets, doesn't create vendor bundles and so forth, in order to create a fast re-build experience when running a dev server (which is essentially why #2327 is, similarly, expected behaviour).
When you are running vue-cli-service build, your NODE_ENV should always be set to production, because that's what you are doing: you are creating a production build. Wether this is intended to be served in a "staging" or "QA" environment or whatever you might call it doesn't matter. It's intended to behave just like your actual production app, except for maybe some ENV Vara that change API URLs to non-production values (which you would do via .env files as explained in the linked documentation).
Does that make it clearer? And if it does, what would you like to read about this in the docs, and where would you expect to find it? We don't always find it easy to get docs for things like this right the first time, as it's hard for someone intimately familiar with a tool to think about things from a new user's perspective on it.
@LinusBorg
Thank you very much for your detailed answer. I understand the intention and behavior now. I had read the docs but didn't quite get it. Now reading them again it's pretty much all there. I will make a suggestion on how to extend it for clarification.
The solution you provide for the build works fine, thanks. I'm using a pipeline to push to the different environments, and I remember I had thought of that solution reading the yellow note on NODE_ENV in the docs, but wasn't happy with it because it doesn't work on Windows and Linux alike. Anyway, it's good enough for now.
What I'm generally wondering is why does NODE_ENV have to match the webpack production mode? The env var will set different URLs or texts or whatever for different environments, whereas the webpack production mode affects the build itself, like which files to include, source maps, pruning and the whole lot. This seems to be not necessarily related to me.
Like in my case, I could want to deploy an app to a dev system or a test system, where the env vars are set accordingly, but the build should be a production build. Would it be awkward to keep NODE_ENV and webpack mode independent?
[edit] And I don't know if that ties in with that, but if my NODE_ENV is set to "test" and I call vue-cli-service build --mode production, it says "Building for production" but builds for test. That is confusing to me. [/edit]
What I'm generally wondering is why does NODE_ENV have to match the webpack production mode?
I think this is another misunderstanding. vue-cli's --mode is not webpack's --mode, it's our own thing.
Webpack's --mode does only a few things (one of them setting NODE_ENV to development or production, by the way).
Our --mode does quite a few more things.
.env, .env.local, .env.${mode} and .env.${mode}.localNODE_ENVNODE_ENV to the matching valueNODE_ENV is then used toSo the point is:
--mode isn't really important here - it's a nice shortcut when you use webpack bare-bones, but not enough for our purposesNODE_ENV is central in the process of determining what primary mode your app is runnning in: development, production or test - and consequently, what kind of webpack config we create etc.--mode sets this NODE_ENV and loads other env variables for the mode that is being set. This allows for e.g. staging environments like explained hereAnd I don't know if that ties in with that, but if my NODE_ENV is set to "test" and I call vue-cli-service build --mode production, it says "Building for production" but builds for test. That is confusing to me.
That's because we never overwrite any environment variable that was being passed in from the system running vue-cli-service.
So --mode is still production, but the NODE_ENV can't be set to production because the system has it predefined.
I'm aware that this is maybe not the most straightforward way to handle this, but it's the best way we found so far that allows for the flexibility we need to support various ways to define env vars and different modes.
Great explanation again, thanks for that. Now I have it, I believe, and enough material to improve the docs :-)
Two more related questions:
So --mode is still production, but the NODE_ENV can't be set to production because the system has it predefined.
That makes sense, but the resulting build should be a production build, no?! If NODE_ENV is "test" and I run vue-cli-service build --mode production, it should be the same as running NODE_ENV=production vue-cli-service build. Currently it's a test build though without assets.
And secondly, when I have an actual production build with all assets included, there's nevertheless an output saying "Images and other types of assets omitted.". Why is that?
That makes sense, but the resulting build should be a production build, no?!
No. As I explained, the NODE_ENV value is what actually determines the kind of webpack config you get. And since we do not overwrite environment variables from the system, you run a build with a test config if your system has defined NODE_ENV=test, which means: images etc are not processed.
As to the second question, I believe that's simply referring to the fact that images and such assets are omitted from the list of created assets that's printrd to the console.
Okay, it's all clarified now, thanks a lot for your help!
Most helpful comment
I think this is another misunderstanding. vue-cli's
--modeis not webpack's--mode, it's our own thing.Webpack's
--modedoes only a few things (one of them settingNODE_ENVtodevelopmentorproduction, by the way).Our
--modedoes quite a few more things..env,.env.local,.env.${mode}and.env.${mode}.localNODE_ENVNODE_ENVto the matching valueNODE_ENVis then used toSo the point is:
--modeisn't really important here - it's a nice shortcut when you use webpack bare-bones, but not enough for our purposesNODE_ENVis central in the process of determining what primary mode your app is runnning in:development,productionortest- and consequently, what kind of webpack config we create etc.--modesets thisNODE_ENVand loads other env variables for the mode that is being set. This allows for e.g. staging environments like explained hereThat's because we never overwrite any environment variable that was being passed in from the system running vue-cli-service.
So
--modeis stillproduction, but the NODE_ENV can't be set toproductionbecause the system has it predefined.I'm aware that this is maybe not the most straightforward way to handle this, but it's the best way we found so far that allows for the flexibility we need to support various ways to define env vars and different modes.