Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolve.extensions cannot be configured properly #176

Closed
zcei opened this issue Jul 18, 2017 · 8 comments
Closed

resolve.extensions cannot be configured properly #176

zcei opened this issue Jul 18, 2017 · 8 comments

Comments

@zcei
Copy link
Collaborator

zcei commented Jul 18, 2017

From @TombolaShepless in #153:

We have resolve.extensions setup so that we can generate different bundles based on device types (e.g. mobile, tablet etc.). However because these two values appear first, Webpack will always resolve the "base" file rather than the override:

import foo from './foo' <--- If we have a foo.mobile file it will never be loaded.

Would it be safer to make no assumptions and have this as an empty array? Or is there an option/method I am missing? Prior to v1 we were using the create vanilla config approach but it looks like this has been removed?

@zcei
Copy link
Collaborator Author

zcei commented Jul 18, 2017

From what I read, the vanilla way is now the default.

I think it's good to have the defaults set, as this is what probably >90% (number out of the blue) of users are doing.

You can set the resolve.extensions, but I guess you know that as it just appends.

What I would find useful is replacing the resolve.extensions when you use resolve({ extensions: ['.custom.js', '.js'] }), because once you modify it you know what you're doing.

Another option would be an extensions(['.custom.js'], config) block, where config could contain keys like this:

{ 
  prepend: true, 
  replace: false, 
  append: false // default 
}

Or directly a string from enum <'prepend','append', 'replace'> as the config parameter.

Examples

extensions(['.custom.js'], 'prepend')
extensions(['.custom.js'], { replace: true })

@andywer what do you think?

@zcei
Copy link
Collaborator Author

zcei commented Jul 18, 2017

Can be done by using smartStrategy

const webpackMerge = require('webpack-merge')

const baseConfig = {
  resolve: {
    // Explicitly define default extensions, otherwise blocks will overwrite them instead of extending
    extensions: ['.js', '.json']
  },
  module: {
    rules: []
  },
  plugins: []
}

const configSnippet = {
  resolve: {
    extensions: ['.custom.js', '.js']
  }
}

const result = webpackMerge.smartStrategy({ 'resolve.extensions': 'replace' })(baseConfig, configSnippet)

// output
{ 
  resolve: { 
    extensions: [ '.custom.js', '.js' ]
  },
  module: { rules: [] },
  plugins: []
}

@andywer
Copy link
Owner

andywer commented Jul 18, 2017

@zcei @TombolaShepless Thanks for your feedback and for creating the issue!

How about we change the behavior of resolve(), so that it prepends the extensions to the existing ones? Sounds like a quickfix or workaround, but I think it makes some sense. This way you would only use the defaults / the extensions you set earlier as a fallback.

@TombolaShepless
Copy link

TombolaShepless commented Jul 18, 2017

@zcei @andywer both of those solutions sound fine to me. If pushed, I'd probably swing towards the prepend approach for a reason @zcei mentioned above:

because once you modify it [extensions] you know what you're doing

If you need anything but standard extensions you (should) know what you want/are doing. Therefore, rather than adding complexity on top of what is a very simple configuration block, it would make more sense to just prepend the custom values.

UPDATE
I guess internally this would look something like this (apologies as Im not savvy with the source code so not sure exactly where this would happen - or if its possible this way):

const config = {
  resolve: {
    extensions: ['.js', '.json']
  }
}

const customExtensions = ['.mobile.js', '.js'];

config.resolve.extensions = [...customExtensions, ...config.resolve.extensions];

console.log(config.resolve.extensions);
// ['.mobile.js', '.js', '.js', '.json']

I guess we could do some clean up to remove dupes?

@zcei
Copy link
Collaborator Author

zcei commented Jul 19, 2017

The dupes shouldn't be of much impact here as it would match the first index and then stops looking further - I guess 😆

If I'm not mistaken, we would only need to change this line:

// before: 
function merge (configSnippet) {
  return prevConfig => webpackMerge.smart(prevConfig, configSnippet)
}

// after
const webpackBlocksMerge = webpackMerge.smartStrategy({ 'resolve.extensions': 'prepend' })

function merge (configSnippet) {
  return prevConfig => webpackBlocksMerge(prevConfig, configSnippet)
}

I like your vanilla solution and usually this would be the go-to way for me, but webpack-merge has some nice benefits in regards of loader de-duplication and other Webpack domain specific knowledge, so I think it should be utilized as much as possible

@andywer
Copy link
Owner

andywer commented Jul 19, 2017

Looks fine to me.

@sapegin @jvanbruegge Objections?

@sapegin
Copy link
Collaborator

sapegin commented Jul 19, 2017

Looks good to me too ;-)

@andywer
Copy link
Owner

andywer commented Jul 30, 2017

Fixed by #177

@andywer andywer closed this as completed Jul 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants