vuejs / vue-cli

🛠️ webpack-based tooling for Vue.js Development
https://cli.vuejs.org/
MIT License
29.76k stars 6.33k forks source link

Eject from Vue CLI / Export Webpack Config #2796

Closed dylanized closed 5 years ago

dylanized commented 6 years ago

What problem does this feature solve?

For advanced projects, a developer might want to customize the Webpack config directly.

This would allow for more granular optimization of build times and serving times, and permit a developer to configure Webpack using their previous Webpack knowledge, instead of being forced to learn the "Vue way". This would align with Vue's goal of being a progressive framework that can be used in different ways.

What does the proposed API look like?

a vue eject or vue export command would generate a Webpack config file. Then the developer could manually delete the Vue config file, and change their tasks to not rely on vue-cli-service.

Akryum commented 6 years ago

You can already use the builtin webpack-merge and webpack-chain tools to change everything in the webpack configuration without having to eject. So there is no benefit of doing so and only downsides.

dylanized commented 6 years ago

I think being able to optimize the build/serve dependencies and speed, at a fine grain level, is a big benefit. I also think there's a project management benefit to knowing that when you spin up a project with Vue CLI, you're not locked into it forever. This makes the decision less risky for organizations that are hesitant on using new tools. (Yes a user take an existing Vue CLI app and retrofit a new Webpack config from scratch, but that is clunky and time consuming).

sirlancelot commented 6 years ago

I would use chainWebpack or configureWebpack for customizing the build. You are given near-complete control over Webpack through these two options. Extracting the internal state of the config can be done easily using either vue inspect or dropping a debugger statement inside your custom configureWebpack function. "Ejecting" is unnecessary and will only create maintenance problems.

LinusBorg commented 6 years ago

I think being able to optimize the build/serve dependencies and speed,

In terms of optimization, I don't see a single thing you could do to an ejected webpack config that you couldn't do with the vue.config.js API. And the construction of this config when running the actual command can't be noticably slower than a slim one on any non-ancient hardware.

The only one little advantage that I can see is that you may be able to get rid of some dependencies during npm install, which with vue-cli-service you will have to install even though you later remove them from the created config.

I also think there's a project management benefit to knowing that when you spin up a project with Vue CLI, you're not locked into it forever.

You're only "locked in" if you define that as "there's no way to eject without me putting some work in".

Ejecting the whole config for all the different ways you might be using it (build with its various flags, different adjustments to configs that are applied when using the unit-jest vs. the unit-mocha plugins etc.) would be pretty hard and clunky.

Yes a user take an existing Vue CLI app and retrofit a new Webpack config from scratch, but that is clunky and time consuming

...but it's actually doable. And for someone who feels limited by the possibilities that our API provides, it should be doable with a bit of work.

So I think we should consider a guide on how to approach this in a reasonable way, but a way of ejecting that actually results in a config that works seamlessly with e.g. webpack-dev-server, a normal build command and a call of /node_modules/.bin/jest isn't really feasable in my opinion.

suau commented 5 years ago

I can see benefits of having a eject feature. While configs merges work, it's a lot easier to predict what the final config looks like if the config is actually present, especially for those who are not very familiar with webpack. There will always be use cases that aren't covered by vue-cli (yet) and for these cases there should be an easy escape hatch.

Just as an example I was looking for adding SSR to the build and found two examples:

  1. https://github.com/eddyerburgh/vue-cli-ssr-example Uses a environment variable to switch between two different overrides for the client/server. Works, but why would I do that if webpack is perfectly capable of handling different build targets.
  2. https://www.npmjs.com/package/@akryum/vue-cli-plugin-ssr A WIP plugin with support for things I'm not using, not sure what it does under the hood or if it works together with other plugins.

Meanwhile there is a nice step by step guide in the vue docs using webpack, no additional plugins/hacks necessary.

LinusBorg commented 5 years ago

An eject feature won't happen in the foreseeable future, as it would be quite complicated to do with the current architecture.

I do agree that our cutomization API, while technically allowing to customize everyting is not 100% as straightforward to use as a webpack config that you have right in front of you.

However that's a tradeoff we are willing to accept.

amoshydra commented 5 years ago

Recently I needed a way to customise webpack in way that vue-cli does not allow.

For example, changing the entry field of the webpack.config in order to achieve this: https://github.com/vuejs/vue-cli/issues/1065#issuecomment-443552579. As of now, vue-cli will always override some of the configuration regardless of what the developer set in vue.config.js e.g.

https://github.com/vuejs/vue-cli/blob/1e200c57261e8badc1412c3af2f8c8253f1d2967/packages/%40vue/cli-service/lib/commands/build/resolveLibConfig.js#L92-L94

However, at the same time, vue-service-cli provide a way for us to read in a base webpack.config.js here https://github.com/vuejs/vue-cli/blob/dc2f8e8/packages/%40vue/cli-service/webpack.config.js

This seems to be quite useful if we need perform any manual configuration to the webpack.config.js. My current setup look like this.

/projectRoot/webpack.config.js

const merge = require('webpack-merge');
const path = require('path');
const util = require('util');
const originalWebpackConfig = require('@vue/cli-service/webpack.config');
const vueConfigWebpackConfig = require('./vue.config').configureWebpack || {};

const isDevEnvironment = (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test');
const fromRoot = (filepath = '') => path.resolve(__dirname, filepath);

// Merge and configure configs
const outputConfig = merge(
  originalWebpackConfig,
  {

Since we will now have our own webpack.config.js, we don't need to rely on vue-cli-service for building/development anymore if you want to.

yarn webpack

Challenge

I can no longer use webpack-chain to configure the webpack. Thus it become quite tedious to configure a plugin (e.g. vue-loader)

gemmi commented 5 years ago

My project is controlled by another VSCODE plugin based on webpack.config.js, this plugin helps me to login and bundle/zip/upload files to server and fails to work without the config file, so if i can't export it,is there a way to fix this problem up with cli3?

jkzing commented 5 years ago

@gemmi, Yes, see https://cli.vuejs.org/guide/webpack.html#using-resolved-config-as-a-file

haoqunjiang commented 5 years ago

The above discussion has made the point quite clear. We won't consider adding this feature in the forseeable future. So I'm closing this issue now.

shirshak55 commented 5 years ago

@sodatea For me vue cli has served its purpose and i no longer need it how can i get like single webpack.config.js so that i can use it with laravel. Using vue cli is always hackier to work with backend like laravel.

I don't want bloat like vue cli uses i want to get clean will it be possible?

haoqunjiang commented 5 years ago

@shirshak55 See https://cli.vuejs.org/guide/webpack.html#inspecting-the-project-s-webpack-config

Akryum commented 5 years ago

I still fail to see why people would want to eject from vue-cli 3. At work we migrated to a custom webpack config to vue-cli in a Rails app it's way cleaner, with way less configuration. And using webpack-chain isn't hacky, it's the cleanest way to customize a pre-defined Webpack configuration.

Benefits of ejecting:

Downsides of ejecting:

shirshak55 commented 5 years ago
vue inspect > output.js

gives no output (no content on output.js)

Benefits of ejecting

We usually don't update vue cli .

And is there any integration with laravel app see evan you version of laravel one is also bit hacky for build

 "build": "rm -rf ../public/{js,css,img} && vue-cli-service build --no-clean",

And create react app has eject feature i don't think there is no reason to keep it

Akryum commented 5 years ago

I don't see what you mean by bloat here.

The small script script above doesn't seem hacky to me.

create-react-app is a simple scaffolding tool which isn't the same as vue-cli 3.

shirshak55 commented 5 years ago

so how can i get simple scaffolding tool for vue :) or should i make custom webpack and use vue loaders etc there?

Akryum commented 5 years ago

What do you think makes vue-cli 3 not simple for you?

shirshak55 commented 5 years ago

create-react-app is a simple scaffolding tool which isn't the same as vue-cli 3.

What do you think makes vue-cli 3 not simple for you?

because its hard to work it laravel . I am currently using vue cli tool . Now i have to deal with cors etc... i want to eject all things so that i can use laravel mix etc.

Akryum commented 5 years ago

Problems integrating with Laravel could be detailed in other issues (but as I said, it's simple to use in a Rails app so...).

gives no output (no content on output.js)

The right part of the docs you should look at is just below: https://cli.vuejs.org/guide/webpack.html#using-resolved-config-as-a-file

shirshak55 commented 5 years ago

@Akryum see this: https://www.youtube.com/watch?v=0KnAhoZ1Kdw&feature=youtu.be it don't work :( and its same for all.

Akryum commented 5 years ago

Please read the docs page until the end. Also your issue with vue inspect is unrelated to this thread.

suau commented 5 years ago

@shirshak55 I struggled with vue-cli-3 as well to the point that I was about to give up on the goodness of webpack 4 + babel 7 and go back to vue-cli-2.

Option 1: Create your own webpack 4 and babel 7 configs and just use those. Use vue inspect to inspect the vue-cli-3 configs (and copy over what is useful for you):

You can also keep using vue-cli for development and just use your own configs for production builds.

Option 2: Use vue-cli-2 instead (this is the simple scaffolding tool you were looking for). It scaffolds your app and then gets out of your way. But the official templates use webpack 3 and babel 6 and thus it's slower and I believe it produces less optimized output.

And the best option of course would be to combine Option 1 and 2 to create a webpack 4 + babel 7 + typescript + ssr + others template for vue-cli-2 and then share it 💃

I personally liked vue-cli-2 and its approach better and think it was a better fit for Vue.

Akryum commented 5 years ago

@suau what was your struggle? One of the goal of vue-cli is having less or no configuration to do compared to vue-cli 2...

shirshak55 commented 5 years ago

@suau thanks :) at least u gave better answer than docs. Yea i like my own config like latest babel typescript etc thats why i prefer ur single webpack config option :)

Thanks i realized i was using yarn global add vue-cli not yarn global add @vue/cli so vue inspect was not working . At least vue cli should have warned i was using vue cli 2 and vue cli 2 should have thrown error on vue inspect command :) Vue Cli is not that easy.

i dont use sass, less and css on vue component etc so i prefer less dependencies and already node is suffering from dependencies hell, single webpack is only the option i think at the moment.

suau commented 5 years ago

@Akryum

@suau what was your struggle? One of the goal of vue-cli is having less or no configuration to do compared to vue-cli 2...

There is no configuration required with vue-cli 2 either, the configs are there but you don't need to touch them.

I had issues adding SSR to vue-cli-3 following the official guide. I really liked the fact that it is designed to only rely on node, everything else is up to you. I'm aware you have written a plugin for that, but a plugin is no replacement for documentation and the ability to edit it manually. There are definitely use cases that are also not covered or options are missing. For example I do need full control over my express server, others might not even use express.

For comparison:

Vue-cli-2

great you've read through the official vue docs and understood most of the options available to you and how it is generally done.

Vue-cli-3

My personal opinion

Personally I happy just running webpack-4 + babel-7 + Typescript + SSR + express. I keep my configs compatible with vue-cli-3, but I'll probably drop that once I've setup caching and HMR.

Akryum commented 5 years ago

As stated in the docs (linked above), vue-cli 3 is compatible with any tool/IDE. For example, to run webpack with it:

webpack --config ./node_modules/@vue/cli-service/webpack.config.js

For your SSR issue which isn't really related to this issue, you can use the connect middleware in your own server (as used with vue-cli-plugin-apollo):

import ssrMiddleware from '@akryum/vue-cli-plugin-ssr/lib/app'

I admit this package documentation is lacking which I'll improve in the near future.

Akryum commented 5 years ago

Make a few choices and vue-cli-2 will scaffold it and set some of the quirky options for you. No knowledge of webpack or babel needed. No editing of config files.

Same with v3 but better, since the choices are more flexible. Then no editing of config files required if the defaults are good for you like in v2.

What's even better now is that common customization required in most projects is easily archived with the basic options in vue.config.js.

Anything scaffolded doesn't suit you need delete it and put whatever you want in there.

If a plugin doesn't suits your need you can indeed uninstall it and write something else to replace it. You can even make your project a sort of "plugin" on its own to get access to the runtime API.

You can also fork the template without too much effort.

This is a trap from v2 which was addressed with v3. Forking a template could seem nice in the beginning, but in the end it's a nightmare to maintain and keep it up-to-date. Poor Typescript team had a very hard time with their template as we updated the official webpack one. The result was all the typescript users using it were almost always left behind.

For options that might not be available during scaffolding go back to the vue docs and use the almost step-by-step guide to add it yourself.

V3 is flexible enough that you can plug any tool to it if it's compatible with Webpack.

If you added something out of vue-cli-2's scope e.g. an express server, you can rely on the vast community using express server for general purposes (or just use what you already know).

Same with V3.

For options that might not be available, go search for a plugin.

Then if the plugin doesn't exist, you can create one or write code directly in your project.

If you found a plugin, but you're having issues, go to the github page of that plugin and try to find a solution there.

If you found a plugin and it generally works, but some options you want to use are missing. Go and try to understand how the plugin system works, fork it and edit the plugin. You are on your own here, because apparently no one has written a vue-cli-plugin for that use case yet.

How is that different from using any package from npm and having issues with it?


From what I get from your post is generally the issues people may encounter are mostly related to docs, resources and migration issues. This can always be improved.

suau commented 5 years ago

Make a few choices and vue-cli-2 will scaffold it and set some of the quirky options for you. No knowledge of webpack or babel needed. No editing of config files.

Same with v3 but better, since the choices are more flexible. Then no editing of config files required if the defaults are good for you like in v2.

What's even better now is that common customization required in most projects is easily archived with the basic options in vue.config.js.

No configs needed for the out of the box experience in both, the webpack configs generated with v2 were also using webpack merge already, merging another vue.config.js should be no issue and chaining should also be no issue here. Updating anything on either v2 or v3 has a good chance of breaking things. On v2 direct customizations to the generated files will be lost. On v3 any changes made to the internal webpack configs have also a good possibility to breaking customizations (merge/chain) in vue.config.js, so do any plugins that touches anything in the build chain. I simply don't see any advantages v3 should have over v2 here.

Anything scaffolded doesn't suit you need delete it and put whatever you want in there.

If a plugin doesn't suits your need you can indeed uninstall it and write something else to replace it. You can even make your project a sort of "plugin" on its own to get access to the runtime API.

Exactly you need to write a vue-specific plugin to get it done. Comparing the search results for webpack + anything vs vue-cli + anything there is a clear winner. And making my project a vue-cli plugin is definitely not what I want to do, the cli should be flexible enough to fit in my project not the other way around.

For options that might not be available during scaffolding go back to the vue docs and use the almost step-by-step guide to add it yourself.

V3 is flexible enough that you can plug any tool to it if it's compatible with Webpack.

Again you need to write a plugin.

If you added something out of vue-cli-2's scope e.g. an express server, you can rely on the vast community using express server for general purposes (or just use what you already know).

Same with V3.

Not really, you still need to write a plugin around everything.

For options that might not be available, go search for a plugin.

Then if the plugin doesn't exist, you can create one or write code directly in your project.

If you found a plugin, but you're having issues, go to the github page of that plugin and try to find a solution there.

If you found a plugin and it generally works, but some options you want to use are missing. Go and try to understand how the plugin system works, fork it and edit the plugin. You are on your own here, because apparently no one has written a vue-cli-plugin for that use case yet.

How is that different from using any package from npm and having issues with it?

It's different because these packages usually have a narrow scope, are general purpose and widely used by all kinds of developers who already ran into the same issue and found a solution, there are tons of resources out there for these. The number of resources you'll find for vue-cli plugin X that uses Y under the hood is going to be so much smaller.

From what I get from your post is generally the issues people may encounter are mostly related to docs, resources and migration issues. This can always be improved.

The docs Vue provided have been great so far, more of it is always welcome. As I said before, personally I'm happy with just the standard tools and plain configs I'm using now. I have no reason to use vue-cli now, but I understand it gets you up and running quickly. That's why I think ejecting would be a great feature to get the best of both.

yyx990803 commented 5 years ago

Ejecting is a typical feature that may sound easy, but is very difficult to get right (or at least it creates an immense extra maintenance burden). You are essentially asking us to put in a LOT of extra work to cater for a niche use case. We are saying no primarily because we don't think this is a worthwhile investment of our limited bandwidth, but there are also other considerations:

The whole premise of CLI 3 is an abstraction layer. It has to take into account not just webpack, but a range of other tools and has to make sure all of them work together as a whole. There's a myriad of combinations of different features that results in different edge cases that we need to watch out for, and they pretty much all result in separate edge cases when ejected into plain text config. In addition, any future changes we make to each plugin or config, we need to do an extra check to make sure it also works after ejection.

More importantly, we want to encourage people to stay away from ejecting so that they get upgrade capabilities in the future. This is important from both a bug fix and security perspective. Ejected users are instantly denied any future upgrades. Any problems they encounter after ejection, we will not be able to confidently triage, because we have no idea how much they have deviated from the default. Making it too easy can lead to many people doing it without realizing what they are giving up.

Some advanced users, like those who have expressed their preference of plain config in this thread, are simply not the target audience of Vue CLI. If you feel more comfortable working with raw config, and consider everything else "bloat" - you are better off starting with your own boilerplate from scratch. You get the full control you want. Alternatively, you can just fork the CLI 2 template and adjust it based on vue inspect output from CLI 3.