vuejs-templates / webpack

A full-featured Webpack + vue-loader setup with hot reload, linting, testing & css extraction.
MIT License
9.7k stars 4.38k forks source link

Disable polyfills in tranform-runtime to prevent dupplicate polyfills. #532

Open sudo-suhas opened 7 years ago

sudo-suhas commented 7 years ago

This issue was also discussed here - https://forum.vuejs.org/t/multiple-promise-libraries-being-exported-in-webpack/6610. My thanks to @LinusBorg

Setup

Module Version
Node.js 6.9.2
npm 4.3
vue-cli 2.8.1
vue 2.1.10
webpack 2.2.1
babel 6.22

Issue details

I have a modified version of the vue-js webpack template which I migrated to webpack 2(some time back) and also made other changes. I have added es6-promise for use with vuex as it needs a Promise library implementation. When I recently used webpack-bundle-analyzer, I saw something odd. A snippet from the vendor.js:

The promise library polyfill is being exported twice. From the discussion with Linus, we were able to conclude that this is happening due to babel-plugin-transform-runtime which, among other things, also introduces polyfills for things likeMap and Promise. This section from babel-loader README is quite relevant but I failed to solve the issue with the bootstrap suggested. Linus suggested that the babel config could be changed to not add polyfills by default:

"plugins": [
  ["transform-runtime", { "polyfill": false}]
]

Are there any polyfills required by vue, vuex and vue-router? I will also try to get rid of the polyfills and check if something breaks.

LinusBorg commented 7 years ago

Vuex uses Promises, so those have to be polyfilled it one wants to support browsers that don't support them natively yet (read: IE <=11).

simplesmiler commented 7 years ago

A side note, es6-promise and es6.promise.js from core-js are different modules, it's not the same module exported twice.

sudo-suhas commented 7 years ago

I tested my app after removing the polyfills and things seem to be working fine. However, note that I am extensively using lodash and not relying on native modules.

LinusBorg commented 7 years ago

@simplesmiler Yeah we are aware of that.

@sudo most of the stuff that tranform-runtime would might polyfill (especially Promises) is available in modern browsers, but might fail in IE11 or even safari

limichange commented 7 years ago

@LinusBorg So, if we want to support most browsers, we need import the two promise polyfill ?

LinusBorg commented 7 years ago

No, that's not what I meant. What I mean is:

If we remove the tranform-runtime (or deactivate the automatic polyfill feature it provides), then you, the developer, have to manually keep track of the polyfill-requiring ES6 features you use include those polyfills if you want to make your app work with out-of-date browsers.

I think we can counter-balance that by switching the es2015 preset for babel-preset-env, especially this feature of that preset, so users can easily add the polyfills that their target browser needs. Maybe that could even be a new option in the setup process.

limichange commented 7 years ago

I agree it. babel-preset-env is better. https://github.com/vuejs-templates/webpack/pull/501

sudo-suhas commented 7 years ago

Although this doesn't matter if transform-runtime is going to be removed, in a different project, the "polyfill": false directive is not being respected. Could have something to do with this issue but I am not calling super() anywhere.

LinusBorg commented 7 years ago

I'm not sure yet weither we want to remove it completely. the helpers part of the plugin is useful, leaving it ouot could clutter the transpiled modules with duplicated helper code.

sudo-suhas commented 7 years ago

I extracted the stats for my webpack chunks and modules by enabling profile and using this plugin. Can anybody please help me understand why the polyfill: false directive is being ignored? The stats.json file can be uploaded here for interactive visualization.

Babel config ```json { "presets": [ ["es2015", { "modules": false }], "stage-1" ], "plugins": [ "lodash", "syntax-dynamic-import", [ "component", [{ "libraryName": "element-ui", "styleLibraryName": "theme-default" }] ], ["transform-runtime", { "polyfill": false }] ], "comments": false, "env": { "test": { "plugins": ["istanbul"] } } } ```

Compressed stats file - stats.json.zip

Edit: I was able to reproduce the issue of polyfill - false being ignored in a fresh copy of the webpack config. When async functions are used, transform-runtime adds transformation ./~/babel-runtime/helpers/asyncToGenerator.js which has a dependency ./~/babel-runtime/core-js/promise.js.

Steps to reproduce:

$ vue init webpack vue-test

  This will install Vue 2.x version of the template.

  For Vue 1.x use: vue init webpack#1.0 vue-test

? Project name vue-test
? Project description Playground for Vue!
? Author Suhas Karanth <sudo.suhas@gmail.com>
? Vue build runtime
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No

   vue-cli · Generated "vue-test".

   To get started:

     cd vue-test
     npm install
     npm run dev

   Documentation can be found at https://vuejs-templates.github.io/webpack

$ cd vue-test/
$ npm install

Modify .babelrc to have ["transform-runtime", { "polyfill": false }].

In main.js:

import Vue from 'vue'
import App from './App'
import router from './router'

async function test() {
    await Promise.resolve(true);
}

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

Now run npm run build --report image

I have reported this as an issue with babel folks but they will probably take some time to resolve it.

LinusBorg commented 7 years ago

@sudo-suhas

the ignore polyfill: false option should be fixed in babel since March, according to the issue you linked.

But I'm not sure the underlying issue is resolved. we switched to babel-preset-env, but still use transfrom-runtime.

TBH I simply haven't looked into this for months and am not 100% sure what's going on under the hood right now concerning polyfills.

Do you have any further results you can share?

sudo-suhas commented 7 years ago

@LinusBorg My understanding was that it was fixed in babel 7.0 which is still in beta. I will check this again sometime this week.

sudo-suhas commented 7 years ago

Apologies for the delay in my response. I tried this out with the latest beta version for babel packages and the issue is not fixed. I have requested that the issue in babel repo be reopened.