Strange polyfill behavior

vue-cli
webpack

#1

I’m having some issues with vue cli 3 polyfilling: 1) If I insert the following into package.json, Promise is polyfilled in the vendor chunk:

  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 9"
  ]
  1. But if I put the same browserslist into a separate .browserslistrc file (removing it from package.json), then Promise is not polyfilled:
> 1%
last 2 versions
not ie <= 9
  1. Or if in package.json I put a different browserslist as follows, Promise is not pollyfilled either:
  "browserslist": [
    "iOS >=9",
    "ChromeAndroid >= 30"
  ]

What in the world is going on here???


#2

Even changing “last 2 versions” to “last 3 versions” break promise polyfill. This is crazy!

  "browserslist": [
    "> 1%",
    "last 3 versions",
    "not ie <= 9"
  ]

#3

I’ll see if I can replicate this, but it would be helpful to have an example repository to try so we look at the exact same thing.

Also, how did you check the vendor chunk? --report?


#4

Thanks. I’ll try to get an example repo a little later.

I checked the vendor chunk in sublime, and searched for finally string to locate promise implementation.


#5

I created a scaffold vue project with vue-cli using the same presets as my project having problems, and it doesn’t seem to have this issue. So I guess there’s something else causing this issue that I need to investigate further.


#6

As a sidenote, I suggest to use vue-cli-service build --report to get a bundle-analyzer report created for you. That allows you to inspect the contents of all chunks i details.


#7

The report shows that core-js modules are missing. So far I’ve narrowed it down that if I add a non-op webpack plugin (like shown below) then core-js is missing. If I remove the plugin, core-js is included. But I can’t repro that in a scaffold project, so something else is going on.

class TestPlugin {
  apply (compiler) {
    //
  }
}

module.exports = {
	configureWebpack: {
		plugins: [new TestPlugin()]
	}
}

#8

I’ve fixed the issue in my project, although I’m not sure exactly what caused it. I narrowed it down to the following in vue.config.js:

const path = require('path')

class TestPlugin {
  apply (compiler) {
    //
  }
}

module.exports = {
	configureWebpack: {
		plugins: [new TestPlugin()]
	},
	chainWebpack: config => {
		config
      		.plugin('copy')
      		.tap(args => {
        		const patterns = args[0]

	          	patterns[0].ignore.push('legacy_stuff/**/*')

				patterns.push({
					from: path.resolve(patterns[0].from, 'legacy_stuff/public'),
					to: 'dist/legacy',
					toType: 'dir',
					// the following ignore breaks core-js bundling, unless slice() is called on it
					ignore: patterns[0].ignore
				})

		        return args
    		})
	}
}

If I use ignore: patterns[0].ignore.slice() instead of ignore: patterns[0].ignore, it works. Again, I can’t repro in the scaffold project, so something else is going on. In my project, that “legacy_stuff” is a complex legacy Sencha Touch project that I’m trying to bring forward into a modern Vue application until I have time to sift it out.


#9

Hi @LinusBorg,

This issue came back again, perhaps from other changes to my build. It seems like there’s something fragile going on. I can’t quite pinpoint it, but it seems related to the ordering of plugins in chainWebpack, as well as usage of the copy plugin.

One thing I noticed in vue-cli source code is that resolveAppConfig has the following code:

  // respect inline build destination in copy plugin
  if (args.dest && config.plugins.has('copy')) {
    config.plugin('copy').tap(args => {
      args[0][0].to = targetDir
      return args
    })
  }

Why is the target specifically updated only on the first pattern. Is that fragile?