How to handle dynamic image paths with webpack












0















I've managed to process the majority of my icons within a large application but there are still two use cases which don't get caught.




  • Dynamic paths used within angular templates
    <md-icon md-svg-src="{{'/assets/icons/ic-' + $ctrl.icon + '.svg'}}"></md-icon>


  • Paths used as varibled within components that are passed to angular templates



i.e something along the lines of



class Comp {
this.settingsLinks = [
{name: 'advanced settings', icon: '/assets/icons/ic-settings.svg'}
]
}


and then that gets used within a template like so



<div ng-repeat="setting in $ctrl.settingsLinks">
<md-icon md-svg-src="{{setting.icon}}"></md-icon>
</div>


My webpack config is like so



module.exports = {
module: {
loaders: [
{
test: /.html$/,
loaders: 'html-loader',
options: {
attrs: ['md-icon:md-svg-src', 'img:ng-src'],
root: path.resolve(__dirname, '../src'),
name: '[name]-[hash].[ext]'
}
},
{
test: /.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
enforce: 'pre'
},
{
test: /.(jpe?g|png|gif|svg)$/,
loader: 'file-loader',
options: {
name() {
return '[name]-[hash].[ext]';
}
}
},
{
test: /.js$/,
exclude: /node_modules/,
loaders: [
'ng-annotate-loader',
'babel-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: conf.path.src('index.html')
}),
new ExtractTextPlugin('index-[contenthash].css'),
],
output: {
path: path.join(process.cwd(), conf.paths.dist),
filename: '[name]-[hash].js'
},
entry: {
app: [`./${conf.path.src('app/app.module.js')}`],
vendor: Object.keys(pkg.dependencies)
},
};


I've been looking at the webpack.ContextReplacementPlugin as a potential way of handling the dynamic paths does anyone have any insight into what I'm trying to achieve? I want to be able to hash names for cache busting purposes but am struggling to work out how to handle dynamic paths in both js and templates.










share|improve this question




















  • 1





    Think you can make use of const require.context('./base/path/to/img/holders', true); The second parameter (TRUE) is to consider subdirectories. You can use a third one to specify regex to search for them. You can access their documentation here

    – Diogo Santo
    Nov 15 '18 at 17:22













  • where would i add this code? instead of the dynamic path?

    – Joe Warner
    Nov 15 '18 at 17:25






  • 1





    Are you able to create a index.js file to start the code up and add it as an entry file? Might find a lot regarding with vue.js but some people seems to go for what you are looking for (from what I understood). Please correct me if I misunderstood. Think this code example might help you further than I will! :x

    – Diogo Santo
    Nov 15 '18 at 17:35











  • so from my understanding that imports in all the possible icons (in this case) so that webpack knows what could be used there? does this have an effect on bundle size or is it entirely webpack based so it can infer what icons could go there?

    – Joe Warner
    Nov 15 '18 at 17:41
















0















I've managed to process the majority of my icons within a large application but there are still two use cases which don't get caught.




  • Dynamic paths used within angular templates
    <md-icon md-svg-src="{{'/assets/icons/ic-' + $ctrl.icon + '.svg'}}"></md-icon>


  • Paths used as varibled within components that are passed to angular templates



i.e something along the lines of



class Comp {
this.settingsLinks = [
{name: 'advanced settings', icon: '/assets/icons/ic-settings.svg'}
]
}


and then that gets used within a template like so



<div ng-repeat="setting in $ctrl.settingsLinks">
<md-icon md-svg-src="{{setting.icon}}"></md-icon>
</div>


My webpack config is like so



module.exports = {
module: {
loaders: [
{
test: /.html$/,
loaders: 'html-loader',
options: {
attrs: ['md-icon:md-svg-src', 'img:ng-src'],
root: path.resolve(__dirname, '../src'),
name: '[name]-[hash].[ext]'
}
},
{
test: /.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
enforce: 'pre'
},
{
test: /.(jpe?g|png|gif|svg)$/,
loader: 'file-loader',
options: {
name() {
return '[name]-[hash].[ext]';
}
}
},
{
test: /.js$/,
exclude: /node_modules/,
loaders: [
'ng-annotate-loader',
'babel-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: conf.path.src('index.html')
}),
new ExtractTextPlugin('index-[contenthash].css'),
],
output: {
path: path.join(process.cwd(), conf.paths.dist),
filename: '[name]-[hash].js'
},
entry: {
app: [`./${conf.path.src('app/app.module.js')}`],
vendor: Object.keys(pkg.dependencies)
},
};


I've been looking at the webpack.ContextReplacementPlugin as a potential way of handling the dynamic paths does anyone have any insight into what I'm trying to achieve? I want to be able to hash names for cache busting purposes but am struggling to work out how to handle dynamic paths in both js and templates.










share|improve this question




















  • 1





    Think you can make use of const require.context('./base/path/to/img/holders', true); The second parameter (TRUE) is to consider subdirectories. You can use a third one to specify regex to search for them. You can access their documentation here

    – Diogo Santo
    Nov 15 '18 at 17:22













  • where would i add this code? instead of the dynamic path?

    – Joe Warner
    Nov 15 '18 at 17:25






  • 1





    Are you able to create a index.js file to start the code up and add it as an entry file? Might find a lot regarding with vue.js but some people seems to go for what you are looking for (from what I understood). Please correct me if I misunderstood. Think this code example might help you further than I will! :x

    – Diogo Santo
    Nov 15 '18 at 17:35











  • so from my understanding that imports in all the possible icons (in this case) so that webpack knows what could be used there? does this have an effect on bundle size or is it entirely webpack based so it can infer what icons could go there?

    – Joe Warner
    Nov 15 '18 at 17:41














0












0








0








I've managed to process the majority of my icons within a large application but there are still two use cases which don't get caught.




  • Dynamic paths used within angular templates
    <md-icon md-svg-src="{{'/assets/icons/ic-' + $ctrl.icon + '.svg'}}"></md-icon>


  • Paths used as varibled within components that are passed to angular templates



i.e something along the lines of



class Comp {
this.settingsLinks = [
{name: 'advanced settings', icon: '/assets/icons/ic-settings.svg'}
]
}


and then that gets used within a template like so



<div ng-repeat="setting in $ctrl.settingsLinks">
<md-icon md-svg-src="{{setting.icon}}"></md-icon>
</div>


My webpack config is like so



module.exports = {
module: {
loaders: [
{
test: /.html$/,
loaders: 'html-loader',
options: {
attrs: ['md-icon:md-svg-src', 'img:ng-src'],
root: path.resolve(__dirname, '../src'),
name: '[name]-[hash].[ext]'
}
},
{
test: /.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
enforce: 'pre'
},
{
test: /.(jpe?g|png|gif|svg)$/,
loader: 'file-loader',
options: {
name() {
return '[name]-[hash].[ext]';
}
}
},
{
test: /.js$/,
exclude: /node_modules/,
loaders: [
'ng-annotate-loader',
'babel-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: conf.path.src('index.html')
}),
new ExtractTextPlugin('index-[contenthash].css'),
],
output: {
path: path.join(process.cwd(), conf.paths.dist),
filename: '[name]-[hash].js'
},
entry: {
app: [`./${conf.path.src('app/app.module.js')}`],
vendor: Object.keys(pkg.dependencies)
},
};


I've been looking at the webpack.ContextReplacementPlugin as a potential way of handling the dynamic paths does anyone have any insight into what I'm trying to achieve? I want to be able to hash names for cache busting purposes but am struggling to work out how to handle dynamic paths in both js and templates.










share|improve this question
















I've managed to process the majority of my icons within a large application but there are still two use cases which don't get caught.




  • Dynamic paths used within angular templates
    <md-icon md-svg-src="{{'/assets/icons/ic-' + $ctrl.icon + '.svg'}}"></md-icon>


  • Paths used as varibled within components that are passed to angular templates



i.e something along the lines of



class Comp {
this.settingsLinks = [
{name: 'advanced settings', icon: '/assets/icons/ic-settings.svg'}
]
}


and then that gets used within a template like so



<div ng-repeat="setting in $ctrl.settingsLinks">
<md-icon md-svg-src="{{setting.icon}}"></md-icon>
</div>


My webpack config is like so



module.exports = {
module: {
loaders: [
{
test: /.html$/,
loaders: 'html-loader',
options: {
attrs: ['md-icon:md-svg-src', 'img:ng-src'],
root: path.resolve(__dirname, '../src'),
name: '[name]-[hash].[ext]'
}
},
{
test: /.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
enforce: 'pre'
},
{
test: /.(jpe?g|png|gif|svg)$/,
loader: 'file-loader',
options: {
name() {
return '[name]-[hash].[ext]';
}
}
},
{
test: /.js$/,
exclude: /node_modules/,
loaders: [
'ng-annotate-loader',
'babel-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: conf.path.src('index.html')
}),
new ExtractTextPlugin('index-[contenthash].css'),
],
output: {
path: path.join(process.cwd(), conf.paths.dist),
filename: '[name]-[hash].js'
},
entry: {
app: [`./${conf.path.src('app/app.module.js')}`],
vendor: Object.keys(pkg.dependencies)
},
};


I've been looking at the webpack.ContextReplacementPlugin as a potential way of handling the dynamic paths does anyone have any insight into what I'm trying to achieve? I want to be able to hash names for cache busting purposes but am struggling to work out how to handle dynamic paths in both js and templates.







javascript angularjs webpack






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 3:17









georgeawg

33.9k105270




33.9k105270










asked Nov 15 '18 at 15:02









Joe WarnerJoe Warner

2,0281523




2,0281523








  • 1





    Think you can make use of const require.context('./base/path/to/img/holders', true); The second parameter (TRUE) is to consider subdirectories. You can use a third one to specify regex to search for them. You can access their documentation here

    – Diogo Santo
    Nov 15 '18 at 17:22













  • where would i add this code? instead of the dynamic path?

    – Joe Warner
    Nov 15 '18 at 17:25






  • 1





    Are you able to create a index.js file to start the code up and add it as an entry file? Might find a lot regarding with vue.js but some people seems to go for what you are looking for (from what I understood). Please correct me if I misunderstood. Think this code example might help you further than I will! :x

    – Diogo Santo
    Nov 15 '18 at 17:35











  • so from my understanding that imports in all the possible icons (in this case) so that webpack knows what could be used there? does this have an effect on bundle size or is it entirely webpack based so it can infer what icons could go there?

    – Joe Warner
    Nov 15 '18 at 17:41














  • 1





    Think you can make use of const require.context('./base/path/to/img/holders', true); The second parameter (TRUE) is to consider subdirectories. You can use a third one to specify regex to search for them. You can access their documentation here

    – Diogo Santo
    Nov 15 '18 at 17:22













  • where would i add this code? instead of the dynamic path?

    – Joe Warner
    Nov 15 '18 at 17:25






  • 1





    Are you able to create a index.js file to start the code up and add it as an entry file? Might find a lot regarding with vue.js but some people seems to go for what you are looking for (from what I understood). Please correct me if I misunderstood. Think this code example might help you further than I will! :x

    – Diogo Santo
    Nov 15 '18 at 17:35











  • so from my understanding that imports in all the possible icons (in this case) so that webpack knows what could be used there? does this have an effect on bundle size or is it entirely webpack based so it can infer what icons could go there?

    – Joe Warner
    Nov 15 '18 at 17:41








1




1





Think you can make use of const require.context('./base/path/to/img/holders', true); The second parameter (TRUE) is to consider subdirectories. You can use a third one to specify regex to search for them. You can access their documentation here

– Diogo Santo
Nov 15 '18 at 17:22







Think you can make use of const require.context('./base/path/to/img/holders', true); The second parameter (TRUE) is to consider subdirectories. You can use a third one to specify regex to search for them. You can access their documentation here

– Diogo Santo
Nov 15 '18 at 17:22















where would i add this code? instead of the dynamic path?

– Joe Warner
Nov 15 '18 at 17:25





where would i add this code? instead of the dynamic path?

– Joe Warner
Nov 15 '18 at 17:25




1




1





Are you able to create a index.js file to start the code up and add it as an entry file? Might find a lot regarding with vue.js but some people seems to go for what you are looking for (from what I understood). Please correct me if I misunderstood. Think this code example might help you further than I will! :x

– Diogo Santo
Nov 15 '18 at 17:35





Are you able to create a index.js file to start the code up and add it as an entry file? Might find a lot regarding with vue.js but some people seems to go for what you are looking for (from what I understood). Please correct me if I misunderstood. Think this code example might help you further than I will! :x

– Diogo Santo
Nov 15 '18 at 17:35













so from my understanding that imports in all the possible icons (in this case) so that webpack knows what could be used there? does this have an effect on bundle size or is it entirely webpack based so it can infer what icons could go there?

– Joe Warner
Nov 15 '18 at 17:41





so from my understanding that imports in all the possible icons (in this case) so that webpack knows what could be used there? does this have an effect on bundle size or is it entirely webpack based so it can infer what icons could go there?

– Joe Warner
Nov 15 '18 at 17:41












1 Answer
1






active

oldest

votes


















0















https://webpack.js.org/guides/dependency-management/




webpack gives access to require.context which allows telling webpack what the dynamic path could/should be, it removed the uncertainty of what is being required and allows you to return the newly hashed icon name from its original name. It does not require them all having an import cost it merely creates a map between the old and new name if I have understood correctly.



for example, this is saying grab all the file names in the icons folder grab the ones starting with ic- as that's our naming scheme for icons, this creates an object at build time I believe of all the possible icons to be used.



const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);



whats returned is a function where you can pass the original icon name and get back the hashed version. You can also use ICONS.keys() to get an array of icons.



here is an example usage I've used to provide some icons.



const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);

export function getIconFromPath(path) {
return ICONS(path);
}

function getIconsFromPaths(obj) {
Object.keys(obj).forEach(key => Object.assign(obj, {[key]: ICONS(obj[key])}));
return obj;
}

export default getIconsFromPaths({
ARCHIVED: './ic-status-warning.svg',
CANCELLED: './ic-status-cancelled.svg',
CONFLICT: './ic-status-warning.svg',
DRAFT: './ic-status-draft.svg',
EARLIER: './ic-status-published.svg',
ENDED: './ic-status-ended.svg',
ERROR: './ic-status-published-failure.svg',
FAILURE: './ic-status-failure.svg',
INVALID: './ic-status-warning.svg',
IN_PROGRESS: './ic-content-publish-in-progress.svg',
LATEST: './ic-status-published-latest.svg',
LOCKED: './ic-status-locked.svg',
PUBLISHED: './ic-status-published.svg',
PUBLISHING: './ic-content-publish-in-progress.svg',
SCHEDULED: './ic-status-scheduled.svg',
SCHEDULING: './ic-content-publish-in-progress.svg',
UNLOCKED: './ic-status-unlocked.svg',
UPDATED: './ic-webhook-request-success.svg',
UNPUBLISHING: './ic-content-publish-in-progress.svg',
UNSCHEDULING: './ic-content-publish-in-progress.svg',
VALID: './ic-content-valid-tick.svg',
WARNING: './ic-status-warning.svg'
});


Because webpack now knows what could be returned from here it can now hash the name and you can do all sorts of good stuff like optimizing at build time.



so the example class given in my question would be resolved by



import { getIconFromPath } from '../icons/;

class Comp {
this.settingsLinks = [
{
name: 'advanced settings',
icon: getIconFromPath('./ic-settings.svg')
}
]
}





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53322288%2fhow-to-handle-dynamic-image-paths-with-webpack%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0















    https://webpack.js.org/guides/dependency-management/




    webpack gives access to require.context which allows telling webpack what the dynamic path could/should be, it removed the uncertainty of what is being required and allows you to return the newly hashed icon name from its original name. It does not require them all having an import cost it merely creates a map between the old and new name if I have understood correctly.



    for example, this is saying grab all the file names in the icons folder grab the ones starting with ic- as that's our naming scheme for icons, this creates an object at build time I believe of all the possible icons to be used.



    const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);



    whats returned is a function where you can pass the original icon name and get back the hashed version. You can also use ICONS.keys() to get an array of icons.



    here is an example usage I've used to provide some icons.



    const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);

    export function getIconFromPath(path) {
    return ICONS(path);
    }

    function getIconsFromPaths(obj) {
    Object.keys(obj).forEach(key => Object.assign(obj, {[key]: ICONS(obj[key])}));
    return obj;
    }

    export default getIconsFromPaths({
    ARCHIVED: './ic-status-warning.svg',
    CANCELLED: './ic-status-cancelled.svg',
    CONFLICT: './ic-status-warning.svg',
    DRAFT: './ic-status-draft.svg',
    EARLIER: './ic-status-published.svg',
    ENDED: './ic-status-ended.svg',
    ERROR: './ic-status-published-failure.svg',
    FAILURE: './ic-status-failure.svg',
    INVALID: './ic-status-warning.svg',
    IN_PROGRESS: './ic-content-publish-in-progress.svg',
    LATEST: './ic-status-published-latest.svg',
    LOCKED: './ic-status-locked.svg',
    PUBLISHED: './ic-status-published.svg',
    PUBLISHING: './ic-content-publish-in-progress.svg',
    SCHEDULED: './ic-status-scheduled.svg',
    SCHEDULING: './ic-content-publish-in-progress.svg',
    UNLOCKED: './ic-status-unlocked.svg',
    UPDATED: './ic-webhook-request-success.svg',
    UNPUBLISHING: './ic-content-publish-in-progress.svg',
    UNSCHEDULING: './ic-content-publish-in-progress.svg',
    VALID: './ic-content-valid-tick.svg',
    WARNING: './ic-status-warning.svg'
    });


    Because webpack now knows what could be returned from here it can now hash the name and you can do all sorts of good stuff like optimizing at build time.



    so the example class given in my question would be resolved by



    import { getIconFromPath } from '../icons/;

    class Comp {
    this.settingsLinks = [
    {
    name: 'advanced settings',
    icon: getIconFromPath('./ic-settings.svg')
    }
    ]
    }





    share|improve this answer




























      0















      https://webpack.js.org/guides/dependency-management/




      webpack gives access to require.context which allows telling webpack what the dynamic path could/should be, it removed the uncertainty of what is being required and allows you to return the newly hashed icon name from its original name. It does not require them all having an import cost it merely creates a map between the old and new name if I have understood correctly.



      for example, this is saying grab all the file names in the icons folder grab the ones starting with ic- as that's our naming scheme for icons, this creates an object at build time I believe of all the possible icons to be used.



      const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);



      whats returned is a function where you can pass the original icon name and get back the hashed version. You can also use ICONS.keys() to get an array of icons.



      here is an example usage I've used to provide some icons.



      const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);

      export function getIconFromPath(path) {
      return ICONS(path);
      }

      function getIconsFromPaths(obj) {
      Object.keys(obj).forEach(key => Object.assign(obj, {[key]: ICONS(obj[key])}));
      return obj;
      }

      export default getIconsFromPaths({
      ARCHIVED: './ic-status-warning.svg',
      CANCELLED: './ic-status-cancelled.svg',
      CONFLICT: './ic-status-warning.svg',
      DRAFT: './ic-status-draft.svg',
      EARLIER: './ic-status-published.svg',
      ENDED: './ic-status-ended.svg',
      ERROR: './ic-status-published-failure.svg',
      FAILURE: './ic-status-failure.svg',
      INVALID: './ic-status-warning.svg',
      IN_PROGRESS: './ic-content-publish-in-progress.svg',
      LATEST: './ic-status-published-latest.svg',
      LOCKED: './ic-status-locked.svg',
      PUBLISHED: './ic-status-published.svg',
      PUBLISHING: './ic-content-publish-in-progress.svg',
      SCHEDULED: './ic-status-scheduled.svg',
      SCHEDULING: './ic-content-publish-in-progress.svg',
      UNLOCKED: './ic-status-unlocked.svg',
      UPDATED: './ic-webhook-request-success.svg',
      UNPUBLISHING: './ic-content-publish-in-progress.svg',
      UNSCHEDULING: './ic-content-publish-in-progress.svg',
      VALID: './ic-content-valid-tick.svg',
      WARNING: './ic-status-warning.svg'
      });


      Because webpack now knows what could be returned from here it can now hash the name and you can do all sorts of good stuff like optimizing at build time.



      so the example class given in my question would be resolved by



      import { getIconFromPath } from '../icons/;

      class Comp {
      this.settingsLinks = [
      {
      name: 'advanced settings',
      icon: getIconFromPath('./ic-settings.svg')
      }
      ]
      }





      share|improve this answer


























        0












        0








        0








        https://webpack.js.org/guides/dependency-management/




        webpack gives access to require.context which allows telling webpack what the dynamic path could/should be, it removed the uncertainty of what is being required and allows you to return the newly hashed icon name from its original name. It does not require them all having an import cost it merely creates a map between the old and new name if I have understood correctly.



        for example, this is saying grab all the file names in the icons folder grab the ones starting with ic- as that's our naming scheme for icons, this creates an object at build time I believe of all the possible icons to be used.



        const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);



        whats returned is a function where you can pass the original icon name and get back the hashed version. You can also use ICONS.keys() to get an array of icons.



        here is an example usage I've used to provide some icons.



        const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);

        export function getIconFromPath(path) {
        return ICONS(path);
        }

        function getIconsFromPaths(obj) {
        Object.keys(obj).forEach(key => Object.assign(obj, {[key]: ICONS(obj[key])}));
        return obj;
        }

        export default getIconsFromPaths({
        ARCHIVED: './ic-status-warning.svg',
        CANCELLED: './ic-status-cancelled.svg',
        CONFLICT: './ic-status-warning.svg',
        DRAFT: './ic-status-draft.svg',
        EARLIER: './ic-status-published.svg',
        ENDED: './ic-status-ended.svg',
        ERROR: './ic-status-published-failure.svg',
        FAILURE: './ic-status-failure.svg',
        INVALID: './ic-status-warning.svg',
        IN_PROGRESS: './ic-content-publish-in-progress.svg',
        LATEST: './ic-status-published-latest.svg',
        LOCKED: './ic-status-locked.svg',
        PUBLISHED: './ic-status-published.svg',
        PUBLISHING: './ic-content-publish-in-progress.svg',
        SCHEDULED: './ic-status-scheduled.svg',
        SCHEDULING: './ic-content-publish-in-progress.svg',
        UNLOCKED: './ic-status-unlocked.svg',
        UPDATED: './ic-webhook-request-success.svg',
        UNPUBLISHING: './ic-content-publish-in-progress.svg',
        UNSCHEDULING: './ic-content-publish-in-progress.svg',
        VALID: './ic-content-valid-tick.svg',
        WARNING: './ic-status-warning.svg'
        });


        Because webpack now knows what could be returned from here it can now hash the name and you can do all sorts of good stuff like optimizing at build time.



        so the example class given in my question would be resolved by



        import { getIconFromPath } from '../icons/;

        class Comp {
        this.settingsLinks = [
        {
        name: 'advanced settings',
        icon: getIconFromPath('./ic-settings.svg')
        }
        ]
        }





        share|improve this answer














        https://webpack.js.org/guides/dependency-management/




        webpack gives access to require.context which allows telling webpack what the dynamic path could/should be, it removed the uncertainty of what is being required and allows you to return the newly hashed icon name from its original name. It does not require them all having an import cost it merely creates a map between the old and new name if I have understood correctly.



        for example, this is saying grab all the file names in the icons folder grab the ones starting with ic- as that's our naming scheme for icons, this creates an object at build time I believe of all the possible icons to be used.



        const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);



        whats returned is a function where you can pass the original icon name and get back the hashed version. You can also use ICONS.keys() to get an array of icons.



        here is an example usage I've used to provide some icons.



        const ICONS = require.context('../../../assets/icons', true, /ic-[a-zA-Z0-9.-]/);

        export function getIconFromPath(path) {
        return ICONS(path);
        }

        function getIconsFromPaths(obj) {
        Object.keys(obj).forEach(key => Object.assign(obj, {[key]: ICONS(obj[key])}));
        return obj;
        }

        export default getIconsFromPaths({
        ARCHIVED: './ic-status-warning.svg',
        CANCELLED: './ic-status-cancelled.svg',
        CONFLICT: './ic-status-warning.svg',
        DRAFT: './ic-status-draft.svg',
        EARLIER: './ic-status-published.svg',
        ENDED: './ic-status-ended.svg',
        ERROR: './ic-status-published-failure.svg',
        FAILURE: './ic-status-failure.svg',
        INVALID: './ic-status-warning.svg',
        IN_PROGRESS: './ic-content-publish-in-progress.svg',
        LATEST: './ic-status-published-latest.svg',
        LOCKED: './ic-status-locked.svg',
        PUBLISHED: './ic-status-published.svg',
        PUBLISHING: './ic-content-publish-in-progress.svg',
        SCHEDULED: './ic-status-scheduled.svg',
        SCHEDULING: './ic-content-publish-in-progress.svg',
        UNLOCKED: './ic-status-unlocked.svg',
        UPDATED: './ic-webhook-request-success.svg',
        UNPUBLISHING: './ic-content-publish-in-progress.svg',
        UNSCHEDULING: './ic-content-publish-in-progress.svg',
        VALID: './ic-content-valid-tick.svg',
        WARNING: './ic-status-warning.svg'
        });


        Because webpack now knows what could be returned from here it can now hash the name and you can do all sorts of good stuff like optimizing at build time.



        so the example class given in my question would be resolved by



        import { getIconFromPath } from '../icons/;

        class Comp {
        this.settingsLinks = [
        {
        name: 'advanced settings',
        icon: getIconFromPath('./ic-settings.svg')
        }
        ]
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 19 '18 at 11:08









        Joe WarnerJoe Warner

        2,0281523




        2,0281523
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53322288%2fhow-to-handle-dynamic-image-paths-with-webpack%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Xamarin.iOS Cant Deploy on Iphone

            Glorious Revolution

            Dulmage-Mendelsohn matrix decomposition in Python