How to handle dynamic image paths with webpack
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
add a comment |
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
1
Think you can make use of constrequire.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
add a comment |
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
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
javascript angularjs webpack
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 constrequire.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
add a comment |
1
Think you can make use of constrequire.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
add a comment |
1 Answer
1
active
oldest
votes
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')
}
]
}
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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')
}
]
}
add a comment |
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')
}
]
}
add a comment |
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')
}
]
}
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')
}
]
}
answered Nov 19 '18 at 11:08
Joe WarnerJoe Warner
2,0281523
2,0281523
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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