eui icon indicating copy to clipboard operation
eui copied to clipboard

Vite/Rollup/ESBuild cannot process the dynamic imports in `EuiIcon`

Open balthild opened this issue 3 years ago • 23 comments

https://github.com/elastic/eui/blob/58b9ca3/src/components/icon/icon.tsx#L627-L633

Here the module paths is constructed by string concatation to satisfy webpack. But vite/rollup has an opposite limitation that module paths must be constructed with template strings, otherwise there'll be a such error:

Edit: seems that I misread the rollup document, but the limitation causes this problem is the module paths do not contain a file extension. It has nothing to do with template strings.

3:12:25 AM [vite] warning: 
/var/www/html/node_modules/.vite/@elastic_eui.js
47876|          return;
47877|        }
47878|        import(
   |               ^
47879|          /* webpackChunkName: "icon.[request]" */
47880|          // It's important that we don't use a template string here, it
The above dynamic import cannot be analyzed by vite.
See https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations for supported dynamic import formats. If this is intended to be left as-is, you can use the /* @vite-ignore */ comment inside the import() call to suppress this warning.

This results in many 404 errors in the application if it uses icons.

balthild avatar Dec 11 '21 03:12 balthild

A workaround, using patch-package:

Click to expand

./patches/@elastic+eui+43.0.0.patch

diff --git a/node_modules/@elastic/eui/es/components/icon/icon.js b/node_modules/@elastic/eui/es/components/icon/icon.js
index d8680f1..1476715 100644
--- a/node_modules/@elastic/eui/es/components/icon/icon.js
+++ b/node_modules/@elastic/eui/es/components/icon/icon.js
@@ -44,6 +44,7 @@ import { enqueueStateChange } from '../../services/react';
 import { htmlIdGenerator } from '../../services';
 import { colorToClassMap, isNamedColor } from './named_colors';
 import { jsx as ___EmotionJSX } from "@emotion/react";
+import { typeToModuleMap } from './icon_imports';
 var typeToPathMap = {
   accessibility: 'accessibility',
   addDataApp: 'app_add_data',
@@ -557,12 +558,7 @@ export var EuiIcon = /*#__PURE__*/function (_PureComponent) {
         return;
       }
 
-      import(
-      /* webpackChunkName: "icon.[request]" */
-      // It's important that we don't use a template string here, it
-      // stops webpack from building a dynamic require context.
-      // eslint-disable-next-line prefer-template
-      './assets/' + typeToPathMap[iconType]).then(function (_ref) {
+      typeToModuleMap[iconType]().then(function (_ref) {
         var icon = _ref.icon;
         iconComponentCache[iconType] = icon;
         enqueueStateChange(function () {
diff --git a/node_modules/@elastic/eui/es/components/icon/icon_imports.js b/node_modules/@elastic/eui/es/components/icon/icon_imports.js
new file mode 100644
index 0000000..bea416e
--- /dev/null
+++ b/node_modules/@elastic/eui/es/components/icon/icon_imports.js
@@ -0,0 +1,436 @@
+export var typeToModuleMap = {
+  accessibility: () => import('./assets/accessibility.js'),
+  addDataApp: () => import('./assets/app_add_data.js'),
+  advancedSettingsApp: () => import('./assets/app_advanced_settings.js'),
+  agentApp: () => import('./assets/app_fleet.js'),
+  aggregate: () => import('./assets/aggregate.js'),
+  alert: () => import('./assets/alert.js'),
+  analyzeEvent: () => import('./assets/analyzeEvent.js'),
+  annotation: () => import('./assets/annotation.js'),
+  apmApp: () => import('./assets/app_apm.js'),
+  apmTrace: () => import('./assets/apm_trace.js'),
+  appSearchApp: () => import('./assets/app_app_search.js'),
+  apps: () => import('./assets/apps.js'),
+  arrowDown: () => import('./assets/arrow_down.js'),
+  arrowLeft: () => import('./assets/arrow_left.js'),
+  arrowRight: () => import('./assets/arrow_right.js'),
+  arrowUp: () => import('./assets/arrow_up.js'),
+  arrowStart: () => import('./assets/arrowStart.js'),
+  arrowEnd: () => import('./assets/arrowEnd.js'),
+  asterisk: () => import('./assets/asterisk.js'),
+  auditbeatApp: () => import('./assets/app_auditbeat.js'),
+  beaker: () => import('./assets/beaker.js'),
+  bell: () => import('./assets/bell.js'),
+  bellSlash: () => import('./assets/bellSlash.js'),
+  bolt: () => import('./assets/bolt.js'),
+  boxesHorizontal: () => import('./assets/boxes_horizontal.js'),
+  boxesVertical: () => import('./assets/boxes_vertical.js'),
+  branch: () => import('./assets/branch.js'),
+  broom: () => import('./assets/broom.js'),
+  brush: () => import('./assets/brush.js'),
+  bug: () => import('./assets/bug.js'),
+  bullseye: () => import('./assets/bullseye.js'),
+  calendar: () => import('./assets/calendar.js'),
+  canvasApp: () => import('./assets/app_canvas.js'),
+  check: () => import('./assets/check.js'),
+  checkInCircleFilled: () => import('./assets/checkInCircleFilled.js'),
+  cheer: () => import('./assets/cheer.js'),
+  classificationJob: () => import('./assets/ml_classification_job.js'),
+  clock: () => import('./assets/clock.js'),
+  cloudDrizzle: () => import('./assets/cloudDrizzle.js'),
+  cloudStormy: () => import('./assets/cloudStormy.js'),
+  cloudSunny: () => import('./assets/cloudSunny.js'),
+  codeApp: () => import('./assets/app_code.js'),
+  color: () => import('./assets/color.js'),
+  compute: () => import('./assets/compute.js'),
+  console: () => import('./assets/console.js'),
+  consoleApp: () => import('./assets/app_console.js'),
+  continuityAbove: () => import('./assets/continuityAbove.js'),
+  continuityAboveBelow: () => import('./assets/continuityAboveBelow.js'),
+  continuityBelow: () => import('./assets/continuityBelow.js'),
+  continuityWithin: () => import('./assets/continuityWithin.js'),
+  controlsHorizontal: () => import('./assets/controls_horizontal.js'),
+  controlsVertical: () => import('./assets/controls_vertical.js'),
+  copy: () => import('./assets/copy.js'),
+  copyClipboard: () => import('./assets/copy_clipboard.js'),
+  createAdvancedJob: () => import('./assets/ml_create_advanced_job.js'),
+  createMultiMetricJob: () => import('./assets/ml_create_multi_metric_job.js'),
+  createPopulationJob: () => import('./assets/ml_create_population_job.js'),
+  createSingleMetricJob: () => import('./assets/ml_create_single_metric_job.js'),
+  cross: () => import('./assets/cross.js'),
+  crossClusterReplicationApp: () => import('./assets/app_cross_cluster_replication.js'),
+  crossInACircleFilled: () => import('./assets/crossInACircleFilled.js'),
+  crosshairs: () => import('./assets/crosshairs.js'),
+  currency: () => import('./assets/currency.js'),
+  cut: () => import('./assets/cut.js'),
+  dashboardApp: () => import('./assets/app_dashboard.js'),
+  dataVisualizer: () => import('./assets/ml_data_visualizer.js'),
+  database: () => import('./assets/database.js'),
+  devToolsApp: () => import('./assets/app_devtools.js'),
+  discoverApp: () => import('./assets/app_discover.js'),
+  document: () => import('./assets/document.js'),
+  documentEdit: () => import('./assets/documentEdit.js'),
+  documentation: () => import('./assets/documentation.js'),
+  documents: () => import('./assets/documents.js'),
+  dot: () => import('./assets/dot.js'),
+  doubleArrowLeft: () => import('./assets/doubleArrowLeft.js'),
+  doubleArrowRight: () => import('./assets/doubleArrowRight.js'),
+  download: () => import('./assets/download.js'),
+  editorAlignCenter: () => import('./assets/editor_align_center.js'),
+  editorAlignLeft: () => import('./assets/editor_align_left.js'),
+  editorAlignRight: () => import('./assets/editor_align_right.js'),
+  editorBold: () => import('./assets/editor_bold.js'),
+  editorCodeBlock: () => import('./assets/editor_code_block.js'),
+  editorComment: () => import('./assets/editor_comment.js'),
+  editorDistributeHorizontal: () => import('./assets/editorDistributeHorizontal.js'),
+  editorDistributeVertical: () => import('./assets/editorDistributeVertical.js'),
+  editorHeading: () => import('./assets/editor_heading.js'),
+  editorItalic: () => import('./assets/editor_italic.js'),
+  editorItemAlignBottom: () => import('./assets/editorItemAlignBottom.js'),
+  editorItemAlignCenter: () => import('./assets/editorItemAlignCenter.js'),
+  editorItemAlignLeft: () => import('./assets/editorItemAlignLeft.js'),
+  editorItemAlignMiddle: () => import('./assets/editorItemAlignMiddle.js'),
+  editorItemAlignRight: () => import('./assets/editorItemAlignRight.js'),
+  editorItemAlignTop: () => import('./assets/editorItemAlignTop.js'),
+  editorLink: () => import('./assets/editor_link.js'),
+  editorOrderedList: () => import('./assets/editor_ordered_list.js'),
+  editorPositionBottomLeft: () => import('./assets/editorPositionBottomLeft.js'),
+  editorPositionBottomRight: () => import('./assets/editorPositionBottomRight.js'),
+  editorPositionTopLeft: () => import('./assets/editorPositionTopLeft.js'),
+  editorPositionTopRight: () => import('./assets/editorPositionTopRight.js'),
+  editorRedo: () => import('./assets/editor_redo.js'),
+  editorStrike: () => import('./assets/editor_strike.js'),
+  editorTable: () => import('./assets/editor_table.js'),
+  editorUnderline: () => import('./assets/editor_underline.js'),
+  editorUndo: () => import('./assets/editor_undo.js'),
+  editorUnorderedList: () => import('./assets/editor_unordered_list.js'),
+  email: () => import('./assets/email.js'),
+  empty: () => import('./assets/empty.js'),
+  emsApp: () => import('./assets/app_ems.js'),
+  eql: () => import('./assets/eql.js'),
+  eraser: () => import('./assets/eraser.js'),
+  exit: () => import('./assets/exit.js'),
+  expand: () => import('./assets/expand.js'),
+  expandMini: () => import('./assets/expandMini.js'),
+  exportAction: () => import('./assets/export.js'),
+  eye: () => import('./assets/eye.js'),
+  eyeClosed: () => import('./assets/eye_closed.js'),
+  faceHappy: () => import('./assets/face_happy.js'),
+  faceNeutral: () => import('./assets/face_neutral.js'),
+  faceSad: () => import('./assets/face_sad.js'),
+  filebeatApp: () => import('./assets/app_filebeat.js'),
+  filter: () => import('./assets/filter.js'),
+  flag: () => import('./assets/flag.js'),
+  fleetApp: () => import('./assets/app_agent.js'),
+  fold: () => import('./assets/fold.js'),
+  folderCheck: () => import('./assets/folder_check.js'),
+  folderClosed: () => import('./assets/folder_closed.js'),
+  folderExclamation: () => import('./assets/folder_exclamation.js'),
+  folderOpen: () => import('./assets/folder_open.js'),
+  frameNext: () => import('./assets/frameNext.js'),
+  framePrevious: () => import('./assets/framePrevious.js'),
+  fullScreen: () => import('./assets/full_screen.js'),
+  fullScreenExit: () => import('./assets/fullScreenExit.js'),
+  function: () => import('./assets/function.js'),
+  gear: () => import('./assets/gear.js'),
+  gisApp: () => import('./assets/app_gis.js'),
+  glasses: () => import('./assets/glasses.js'),
+  globe: () => import('./assets/globe.js'),
+  grab: () => import('./assets/grab.js'),
+  grabHorizontal: () => import('./assets/grab_horizontal.js'),
+  graphApp: () => import('./assets/app_graph.js'),
+  grid: () => import('./assets/grid.js'),
+  grokApp: () => import('./assets/app_grok.js'),
+  heart: () => import('./assets/heart.js'),
+  heartbeatApp: () => import('./assets/app_heartbeat.js'),
+  heatmap: () => import('./assets/heatmap.js'),
+  help: () => import('./assets/help.js'),
+  home: () => import('./assets/home.js'),
+  iInCircle: () => import('./assets/iInCircle.js'),
+  image: () => import('./assets/image.js'),
+  importAction: () => import('./assets/import.js'),
+  indexClose: () => import('./assets/index_close.js'),
+  indexEdit: () => import('./assets/index_edit.js'),
+  indexFlush: () => import('./assets/index_flush.js'),
+  indexManagementApp: () => import('./assets/app_index_management.js'),
+  indexMapping: () => import('./assets/index_mapping.js'),
+  indexOpen: () => import('./assets/index_open.js'),
+  indexPatternApp: () => import('./assets/app_index_pattern.js'),
+  indexRollupApp: () => import('./assets/app_index_rollup.js'),
+  indexRuntime: () => import('./assets/index_runtime.js'),
+  indexSettings: () => import('./assets/index_settings.js'),
+  inputOutput: () => import('./assets/inputOutput.js'),
+  inspect: () => import('./assets/inspect.js'),
+  invert: () => import('./assets/invert.js'),
+  ip: () => import('./assets/ip.js'),
+  keyboardShortcut: () => import('./assets/keyboard_shortcut.js'),
+  kqlField: () => import('./assets/kql_field.js'),
+  kqlFunction: () => import('./assets/kql_function.js'),
+  kqlOperand: () => import('./assets/kql_operand.js'),
+  kqlSelector: () => import('./assets/kql_selector.js'),
+  kqlValue: () => import('./assets/kql_value.js'),
+  layers: () => import('./assets/layers.js'),
+  lensApp: () => import('./assets/app_lens.js'),
+  link: () => import('./assets/link.js'),
+  list: () => import('./assets/list.js'),
+  listAdd: () => import('./assets/list_add.js'),
+  lock: () => import('./assets/lock.js'),
+  lockOpen: () => import('./assets/lockOpen.js'),
+  logoAWS: () => import('./assets/logo_aws.js'),
+  logoAWSMono: () => import('./assets/logo_aws_mono.js'),
+  logoAerospike: () => import('./assets/logo_aerospike.js'),
+  logoApache: () => import('./assets/logo_apache.js'),
+  logoAppSearch: () => import('./assets/logo_app_search.js'),
+  logoAzure: () => import('./assets/logo_azure.js'),
+  logoAzureMono: () => import('./assets/logo_azure_mono.js'),
+  logoBeats: () => import('./assets/logo_beats.js'),
+  logoBusinessAnalytics: () => import('./assets/logo_business_analytics.js'),
+  logoCeph: () => import('./assets/logo_ceph.js'),
+  logoCloud: () => import('./assets/logo_cloud.js'),
+  logoCloudEnterprise: () => import('./assets/logo_cloud_ece.js'),
+  logoCode: () => import('./assets/logo_code.js'),
+  logoCodesandbox: () => import('./assets/logo_codesandbox.js'),
+  logoCouchbase: () => import('./assets/logo_couchbase.js'),
+  logoDocker: () => import('./assets/logo_docker.js'),
+  logoDropwizard: () => import('./assets/logo_dropwizard.js'),
+  logoElastic: () => import('./assets/logo_elastic.js'),
+  logoElasticStack: () => import('./assets/logo_elastic_stack.js'),
+  logoElasticsearch: () => import('./assets/logo_elasticsearch.js'),
+  logoEnterpriseSearch: () => import('./assets/logo_enterprise_search.js'),
+  logoEtcd: () => import('./assets/logo_etcd.js'),
+  logoGCP: () => import('./assets/logo_gcp.js'),
+  logoGCPMono: () => import('./assets/logo_gcp_mono.js'),
+  logoGithub: () => import('./assets/logo_github.js'),
+  logoGmail: () => import('./assets/logo_gmail.js'),
+  logoGolang: () => import('./assets/logo_golang.js'),
+  logoGoogleG: () => import('./assets/logo_google_g.js'),
+  logoHAproxy: () => import('./assets/logo_haproxy.js'),
+  logoIBM: () => import('./assets/logo_ibm.js'),
+  logoIBMMono: () => import('./assets/logo_ibm_mono.js'),
+  logoKafka: () => import('./assets/logo_kafka.js'),
+  logoKibana: () => import('./assets/logo_kibana.js'),
+  logoKubernetes: () => import('./assets/logo_kubernetes.js'),
+  logoLogging: () => import('./assets/logo_logging.js'),
+  logoLogstash: () => import('./assets/logo_logstash.js'),
+  logoMaps: () => import('./assets/logo_maps.js'),
+  logoMemcached: () => import('./assets/logo_memcached.js'),
+  logoMetrics: () => import('./assets/logo_metrics.js'),
+  logoMongodb: () => import('./assets/logo_mongodb.js'),
+  logoMySQL: () => import('./assets/logo_mysql.js'),
+  logoNginx: () => import('./assets/logo_nginx.js'),
+  logoObservability: () => import('./assets/logo_observability.js'),
+  logoOsquery: () => import('./assets/logo_osquery.js'),
+  logoPhp: () => import('./assets/logo_php.js'),
+  logoPostgres: () => import('./assets/logo_postgres.js'),
+  logoPrometheus: () => import('./assets/logo_prometheus.js'),
+  logoRabbitmq: () => import('./assets/logo_rabbitmq.js'),
+  logoRedis: () => import('./assets/logo_redis.js'),
+  logoSecurity: () => import('./assets/logo_security.js'),
+  logoSiteSearch: () => import('./assets/logo_site_search.js'),
+  logoSketch: () => import('./assets/logo_sketch.js'),
+  logoSlack: () => import('./assets/logo_slack.js'),
+  logoUptime: () => import('./assets/logo_uptime.js'),
+  logoWebhook: () => import('./assets/logo_webhook.js'),
+  logoWindows: () => import('./assets/logo_windows.js'),
+  logoWorkplaceSearch: () => import('./assets/logo_workplace_search.js'),
+  logsApp: () => import('./assets/app_logs.js'),
+  logstashFilter: () => import('./assets/logstash_filter.js'),
+  logstashIf: () => import('./assets/logstash_if.js'),
+  logstashInput: () => import('./assets/logstash_input.js'),
+  logstashOutput: () => import('./assets/logstash_output.js'),
+  logstashQueue: () => import('./assets/logstash_queue.js'),
+  machineLearningApp: () => import('./assets/app_ml.js'),
+  magnet: () => import('./assets/magnet.js'),
+  magnifyWithMinus: () => import('./assets/magnifyWithMinus.js'),
+  magnifyWithPlus: () => import('./assets/magnifyWithPlus.js'),
+  managementApp: () => import('./assets/app_management.js'),
+  mapMarker: () => import('./assets/map_marker.js'),
+  memory: () => import('./assets/memory.js'),
+  menu: () => import('./assets/menu.js'),
+  menuDown: () => import('./assets/menuDown.js'),
+  menuLeft: () => import('./assets/menuLeft.js'),
+  menuRight: () => import('./assets/menuRight.js'),
+  menuUp: () => import('./assets/menuUp.js'),
+  merge: () => import('./assets/merge.js'),
+  metricbeatApp: () => import('./assets/app_metricbeat.js'),
+  metricsApp: () => import('./assets/app_metrics.js'),
+  minimize: () => import('./assets/minimize.js'),
+  minus: () => import('./assets/minus.js'),
+  minusInCircle: () => import('./assets/minus_in_circle.js'),
+  minusInCircleFilled: () => import('./assets/minus_in_circle_filled.js'),
+  mobile: () => import('./assets/mobile.js'),
+  monitoringApp: () => import('./assets/app_monitoring.js'),
+  moon: () => import('./assets/moon.js'),
+  nested: () => import('./assets/nested.js'),
+  node: () => import('./assets/node.js'),
+  notebookApp: () => import('./assets/app_notebook.js'),
+  number: () => import('./assets/number.js'),
+  offline: () => import('./assets/offline.js'),
+  online: () => import('./assets/online.js'),
+  outlierDetectionJob: () => import('./assets/ml_outlier_detection_job.js'),
+  package: () => import('./assets/package.js'),
+  packetbeatApp: () => import('./assets/app_packetbeat.js'),
+  pageSelect: () => import('./assets/pageSelect.js'),
+  pagesSelect: () => import('./assets/pagesSelect.js'),
+  paperClip: () => import('./assets/paper_clip.js'),
+  partial: () => import('./assets/partial.js'),
+  pause: () => import('./assets/pause.js'),
+  payment: () => import('./assets/payment.js'),
+  pencil: () => import('./assets/pencil.js'),
+  percent: () => import('./assets/percent.js'),
+  pin: () => import('./assets/pin.js'),
+  pinFilled: () => import('./assets/pin_filled.js'),
+  pipelineApp: () => import('./assets/app_pipeline.js'),
+  play: () => import('./assets/play.js'),
+  playFilled: () => import('./assets/playFilled.js'),
+  plus: () => import('./assets/plus.js'),
+  plusInCircle: () => import('./assets/plus_in_circle.js'),
+  plusInCircleFilled: () => import('./assets/plus_in_circle_filled.js'),
+  popout: () => import('./assets/popout.js'),
+  push: () => import('./assets/push.js'),
+  questionInCircle: () => import('./assets/question_in_circle.js'),
+  quote: () => import('./assets/quote.js'),
+  recentlyViewedApp: () => import('./assets/app_recently_viewed.js'),
+  refresh: () => import('./assets/refresh.js'),
+  regressionJob: () => import('./assets/ml_regression_job.js'),
+  reporter: () => import('./assets/reporter.js'),
+  reportingApp: () => import('./assets/app_reporting.js'),
+  returnKey: () => import('./assets/return_key.js'),
+  save: () => import('./assets/save.js'),
+  savedObjectsApp: () => import('./assets/app_saved_objects.js'),
+  scale: () => import('./assets/scale.js'),
+  search: () => import('./assets/search.js'),
+  searchProfilerApp: () => import('./assets/app_search_profiler.js'),
+  securityAnalyticsApp: () => import('./assets/app_security_analytics.js'),
+  securityApp: () => import('./assets/app_security.js'),
+  securitySignal: () => import('./assets/securitySignal.js'),
+  securitySignalDetected: () => import('./assets/securitySignalDetected.js'),
+  securitySignalResolved: () => import('./assets/securitySignalResolved.js'),
+  shard: () => import('./assets/shard.js'),
+  share: () => import('./assets/share.js'),
+  snowflake: () => import('./assets/snowflake.js'),
+  sortDown: () => import('./assets/sort_down.js'),
+  sortLeft: () => import('./assets/sortLeft.js'),
+  sortRight: () => import('./assets/sortRight.js'),
+  sortUp: () => import('./assets/sort_up.js'),
+  sortable: () => import('./assets/sortable.js'),
+  spacesApp: () => import('./assets/app_spaces.js'),
+  sqlApp: () => import('./assets/app_sql.js'),
+  starEmpty: () => import('./assets/star_empty.js'),
+  starEmptySpace: () => import('./assets/star_empty_space.js'),
+  starFilled: () => import('./assets/star_filled.js'),
+  starFilledSpace: () => import('./assets/star_filled_space.js'),
+  starMinusEmpty: () => import('./assets/star_minus_empty.js'),
+  starMinusFilled: () => import('./assets/star_minus_filled.js'),
+  starPlusEmpty: () => import('./assets/starPlusEmpty.js'),
+  starPlusFilled: () => import('./assets/starPlusFilled.js'),
+  stats: () => import('./assets/stats.js'),
+  stop: () => import('./assets/stop.js'),
+  stopFilled: () => import('./assets/stop_filled.js'),
+  stopSlash: () => import('./assets/stop_slash.js'),
+  storage: () => import('./assets/storage.js'),
+  string: () => import('./assets/string.js'),
+  submodule: () => import('./assets/submodule.js'),
+  swatchInput: () => import('./assets/swatch_input.js'),
+  // Undocumented on purpose. Has an extra stroke for EuiColorPicker
+  symlink: () => import('./assets/symlink.js'),
+  tableDensityCompact: () => import('./assets/table_density_compact.js'),
+  tableDensityExpanded: () => import('./assets/table_density_expanded.js'),
+  tableDensityNormal: () => import('./assets/table_density_normal.js'),
+  tableOfContents: () => import('./assets/tableOfContents.js'),
+  tag: () => import('./assets/tag.js'),
+  tear: () => import('./assets/tear.js'),
+  temperature: () => import('./assets/temperature.js'),
+  timeline: () => import('./assets/timeline.js'),
+  timelionApp: () => import('./assets/app_timelion.js'),
+  timeRefresh: () => import('./assets/timeRefresh.js'),
+  timeslider: () => import('./assets/timeslider.js'),
+  training: () => import('./assets/training.js'),
+  trash: () => import('./assets/trash.js'),
+  unfold: () => import('./assets/unfold.js'),
+  unlink: () => import('./assets/unlink.js'),
+  upgradeAssistantApp: () => import('./assets/app_upgrade_assistant.js'),
+  uptimeApp: () => import('./assets/app_uptime.js'),
+  user: () => import('./assets/user.js'),
+  users: () => import('./assets/users.js'),
+  usersRolesApp: () => import('./assets/app_users_roles.js'),
+  vector: () => import('./assets/vector.js'),
+  videoPlayer: () => import('./assets/videoPlayer.js'),
+  visArea: () => import('./assets/vis_area.js'),
+  visAreaStacked: () => import('./assets/vis_area_stacked.js'),
+  visBarHorizontal: () => import('./assets/vis_bar_horizontal.js'),
+  visBarHorizontalStacked: () => import('./assets/vis_bar_horizontal_stacked.js'),
+  visBarVertical: () => import('./assets/vis_bar_vertical.js'),
+  visBarVerticalStacked: () => import('./assets/vis_bar_vertical_stacked.js'),
+  visGauge: () => import('./assets/vis_gauge.js'),
+  visGoal: () => import('./assets/vis_goal.js'),
+  visLine: () => import('./assets/vis_line.js'),
+  visMapCoordinate: () => import('./assets/vis_map_coordinate.js'),
+  visMapRegion: () => import('./assets/vis_map_region.js'),
+  visMetric: () => import('./assets/vis_metric.js'),
+  visPie: () => import('./assets/vis_pie.js'),
+  visTable: () => import('./assets/vis_table.js'),
+  visTagCloud: () => import('./assets/vis_tag_cloud.js'),
+  visText: () => import('./assets/vis_text.js'),
+  visTimelion: () => import('./assets/vis_timelion.js'),
+  visVega: () => import('./assets/vis_vega.js'),
+  visVisualBuilder: () => import('./assets/vis_visual_builder.js'),
+  visualizeApp: () => import('./assets/app_visualize.js'),
+  watchesApp: () => import('./assets/app_watches.js'),
+  wordWrap: () => import('./assets/wordWrap.js'),
+  wordWrapDisabled: () => import('./assets/wordWrapDisabled.js'),
+  workplaceSearchApp: () => import('./assets/app_workplace_search.js'),
+  wrench: () => import('./assets/wrench.js'),
+  // Token Icon Imports
+  tokenClass: () => import('./assets/tokenClass.js'),
+  tokenProperty: () => import('./assets/tokenProperty.js'),
+  tokenEnum: () => import('./assets/tokenEnum.js'),
+  tokenVariable: () => import('./assets/tokenVariable.js'),
+  tokenMethod: () => import('./assets/tokenMethod.js'),
+  tokenAnnotation: () => import('./assets/tokenAnnotation.js'),
+  tokenException: () => import('./assets/tokenException.js'),
+  tokenInterface: () => import('./assets/tokenInterface.js'),
+  tokenParameter: () => import('./assets/tokenParameter.js'),
+  tokenField: () => import('./assets/tokenField.js'),
+  tokenElement: () => import('./assets/tokenElement.js'),
+  tokenFunction: () => import('./assets/tokenFunction.js'),
+  tokenBoolean: () => import('./assets/tokenBoolean.js'),
+  tokenString: () => import('./assets/tokenString.js'),
+  tokenArray: () => import('./assets/tokenArray.js'),
+  tokenNumber: () => import('./assets/tokenNumber.js'),
+  tokenConstant: () => import('./assets/tokenConstant.js'),
+  tokenObject: () => import('./assets/tokenObject.js'),
+  tokenEvent: () => import('./assets/tokenEvent.js'),
+  tokenKey: () => import('./assets/tokenKey.js'),
+  tokenNull: () => import('./assets/tokenNull.js'),
+  tokenStruct: () => import('./assets/tokenStruct.js'),
+  tokenPackage: () => import('./assets/tokenPackage.js'),
+  tokenOperator: () => import('./assets/tokenOperator.js'),
+  tokenEnumMember: () => import('./assets/tokenEnumMember.js'),
+  tokenRepo: () => import('./assets/tokenRepo.js'),
+  tokenSymbol: () => import('./assets/tokenSymbol.js'),
+  tokenFile: () => import('./assets/tokenFile.js'),
+  tokenModule: () => import('./assets/tokenModule.js'),
+  tokenNamespace: () => import('./assets/tokenNamespace.js'),
+  tokenDate: () => import('./assets/tokenDate.js'),
+  tokenIP: () => import('./assets/tokenIP.js'),
+  tokenNested: () => import('./assets/tokenNested.js'),
+  tokenAlias: () => import('./assets/tokenAlias.js'),
+  tokenShape: () => import('./assets/tokenShape.js'),
+  tokenGeo: () => import('./assets/tokenGeo.js'),
+  tokenRange: () => import('./assets/tokenRange.js'),
+  tokenBinary: () => import('./assets/tokenBinary.js'),
+  tokenJoin: () => import('./assets/tokenJoin.js'),
+  tokenPercolator: () => import('./assets/tokenPercolator.js'),
+  tokenFlattened: () => import('./assets/tokenFlattened.js'),
+  tokenRankFeature: () => import('./assets/tokenRankFeature.js'),
+  tokenRankFeatures: () => import('./assets/tokenRankFeatures.js'),
+  tokenKeyword: () => import('./assets/tokenKeyword.js'),
+  tokenTag: () => import('./assets/tokenTag.js'),
+  tokenCompletionSuggester: () => import('./assets/tokenCompletionSuggester.js'),
+  tokenDenseVector: () => import('./assets/tokenDenseVector.js'),
+  tokenText: () => import('./assets/tokenText.js'),
+  tokenTokenCount: () => import('./assets/tokenTokenCount.js'),
+  tokenSearchType: () => import('./assets/tokenSearchType.js'),
+  tokenHistogram: () => import('./assets/tokenHistogram.js')
+};

balthild avatar Dec 12 '21 06:12 balthild

Thanks for finding this @balthild! For context, I removed the concatenated .js extension in https://github.com/elastic/eui/pull/5212 because local dev now uses Typescript / .tsx but production still compiles to .js, and Webpack was smart enough to find either the .tsx or .js version of it. I definitely didn't think of other bundlers like Rollup 🤦‍♀️

I think an easy/okay solution could be detect whether we're in dev vs prod and output .tsx vs .js with that in some kind of ternary. So on line 632, something like

'./assets/' + typeToPathMap[iconType] + (process.env.NODE_ENV !== 'production' ? '.tsx' : '.js')

No idea if EUI is setting NODE_ENV however or how that would actually work in a consumer environment, so someone should definitely double check that or find a condition that works 🙈

cee-chen avatar Dec 14 '21 16:12 cee-chen

I'm not sure if vite could recognize a conditional string now, but I've find that I'm running into another problem that prevents us to confirm this - vite does not transpile the dynamic imports in a dependency module at all (vitejs/vite#6179). This is why the workaround I'd posted above adds a long typeToModuleMap object rather than simply adds .js file extension to the import expression. I think this issue is therefore not possible to fix before vitejs/vite#6179 is fixed.

balthild avatar Dec 19 '21 13:12 balthild

Ahhh, gotcha. Another alternative for consuming EuiIcons is how SSRs handle it: https://github.com/elastic/eui/tree/main/wiki/consuming-eui#failing-icon-imports

cee-chen avatar Dec 20 '21 16:12 cee-chen

Vite user here. Using the appendIconComponentCache() method works well enough when I'm creating my own components. The DX falls down when adding components with many different icons (such as EuiInMemoryTable) because I have to search the source code. It would be nice to have a list of icons the component uses in the docs.

henry-young avatar Apr 22 '22 00:04 henry-young

Hi @henry-young, I use Vite too and have run into a similar problem. How did you get the appendIconComponentCache function to work? Could you give an example of its use in Vite?

TomSoldier avatar Apr 22 '22 23:04 TomSoldier

Hi @henry-young, I use Vite too and have run into a similar problem. How did you get the appendIconComponentCache function to work? Could you give an example of its use in Vite?

Firstly in vite.config.js I added

export default defineConfig({
  ...
  build: {
   ...
    dynamicImportVarsOptions: {
      exclude: [],
    },
  },
  ...
});

and then I just have a file named ~/src/icons.ts that contains.

import { ICON_TYPES } from '@elastic/eui';
import { ValuesType } from 'utility-types';

import { appendIconComponentCache } from '@elastic/eui/es/components/icon/icon';

import { icon as magnifyWithMinus } from '@elastic/eui/es/components/icon/assets/magnifyWithMinus';
import { icon as minus } from '@elastic/eui/es/components/icon/assets/minus';
import { icon as magnifyWithPlus } from '@elastic/eui/es/components/icon/assets/magnifyWithPlus';
import { icon as plus } from '@elastic/eui/es/components/icon/assets/plus';

type IconComponentNameType = ValuesType<typeof ICON_TYPES>;
type IconComponentCacheType = Partial<Record<IconComponentNameType, unknown>>;

const cachedIcons: IconComponentCacheType = {
  magnifyWithMinus,
  magnifyWithPlus,
  minus,
  plus,
  ...
};

appendIconComponentCache(cachedIcons);

And then a global.d.ts file containing a basic module definition for the icons (so typescript doesn't complain)

declare module '@elastic/eui/es/components/icon/*';

I hope that helps.

henry-young avatar Apr 23 '22 23:04 henry-young

Hi @henry-young, I use Vite too and have run into a similar problem. How did you get the appendIconComponentCache function to work? Could you give an example of its use in Vite?

Firstly in vite.config.js I added

export default defineConfig({
  ...
  build: {
   ...
    dynamicImportVarsOptions: {
      exclude: [],
    },
  },
  ...
});

and then I just have a file named ~/src/icons.ts that contains.

import { ICON_TYPES } from '@elastic/eui';
import { ValuesType } from 'utility-types';

import { appendIconComponentCache } from '@elastic/eui/es/components/icon/icon';

import { icon as magnifyWithMinus } from '@elastic/eui/es/components/icon/assets/magnifyWithMinus';
import { icon as minus } from '@elastic/eui/es/components/icon/assets/minus';
import { icon as magnifyWithPlus } from '@elastic/eui/es/components/icon/assets/magnifyWithPlus';
import { icon as plus } from '@elastic/eui/es/components/icon/assets/plus';

type IconComponentNameType = ValuesType<typeof ICON_TYPES>;
type IconComponentCacheType = Partial<Record<IconComponentNameType, unknown>>;

const cachedIcons: IconComponentCacheType = {
  magnifyWithMinus,
  magnifyWithPlus,
  minus,
  plus,
  ...
};

appendIconComponentCache(cachedIcons);

And then a global.d.ts file containing a basic module definition for the icons (so typescript doesn't complain)

declare module '@elastic/eui/es/components/icon/*';

I hope that helps.

Thank you, I understand how it works now. I missed the module declaration.

TomSoldier avatar Apr 23 '22 23:04 TomSoldier

Thanks for posting that super detailed comment @henry-young!

It would be nice to have a list of icons the component uses in the docs.

Maybe I'm missing something, but you definitely shouldn't have to search our source code to look at a list of all our icons - they should be available for preview/search at https://elastic.github.io/eui/#/display/icons#glyphs (you can click the icon to copy the iconType). Hope that helps!

cee-chen avatar Apr 25 '22 16:04 cee-chen

Thanks for posting that super detailed comment @henry-young!

It would be nice to have a list of icons the component uses in the docs.

Maybe I'm missing something, but you definitely shouldn't have to search our source code to look at a list of all our icons - they should be available for preview/search at https://elastic.github.io/eui/#/display/icons#glyphs (you can click the icon to copy the iconType). Hope that helps!

@constancecchen , I think he thought, for example, that the API pages of table components like EuiTable doesn't have the names of the icons used by the component, so it's hard to know what icons we want to cache. The same is true for other components that use built-in icons.

TomSoldier avatar Apr 25 '22 17:04 TomSoldier

Ah, you're totally right, I missed that context, apologies! We're not likely to update our docs to include a list of all icons each component uses as SSR consumers are still an edge case for us (and for the original issue, the file extension issue can be addressed either by Vite or EUI) - but as Henry did it's possible for consumers to grep through our source code for components looking for either EuiIcon or iconType.

cee-chen avatar Apr 25 '22 17:04 cee-chen

I use Parcel bundler and I have the same issue. As I don't like to add each icon by hand, I made a patch for the latest version of Elastic UI : https://gist.github.com/badwulfy/2a59c5ab8866439ff074e05e136b653d

badwulfy avatar Jul 12 '22 15:07 badwulfy

We had a brief sync about this today, and we'd be open to changing the import method. One difficulty I see with the referenced path is that we have 4 different builds (es, lib, optimize/es, and optimize/lib) and the import path would need to change for each:

accessibility: () => import('@elastic/eui/es/components/icon/assets/accessibility')

Right now each build, as well as local dev (with webpack dev server), work because of the relative './assets/' pathing in the concatenated string. We'd need to alter the import at build time to accommodate each build but keep local imports working for dev environments.

thompsongl avatar Jul 12 '22 19:07 thompsongl

+1 for having a simpler solution, but nice to have a workaround. I'm using Vite.

jgentes avatar Aug 15 '22 01:08 jgentes

Out of curiosity, why is a dynamic import needed here? Why not just rely on tree-shaking?

For those applying the patch now, you need to remove keyboardShortcut (I've not checked for any new icons)

j-m avatar Jan 26 '23 18:01 j-m

and then I just have a file named ~/src/icons.ts that contains.

@henry-young What do I do with icons.ts? Do I have to import it somewhere or put it in vite.config.js? I follow your work around but icons are still not showing up.

lightwave avatar Feb 13 '23 05:02 lightwave

and then I just have a file named ~/src/icons.ts that contains.

@henry-young What do I do with icons.ts? Do I have to import it somewhere or put it in vite.config.js? I follow your work around but icons are still not showing up.

I put import "~/src/icons"; at the top of my main.tsx (the file containing ReactDOM.render()). I do this to make sure that the icon cache code is run before the app starts.

You could wrap appendIconComponentCache(cachedIcons); in a function and export it so you could execute that exactly when you want it to. I didn't have a need to do it that way, but you might if that suits your needs.

henry-young avatar Feb 13 '23 06:02 henry-young

@henry-young Thanks! That works perfectly.

lightwave avatar Feb 13 '23 15:02 lightwave

Thanks me later: https://gist.github.com/unckleg/5476ebd940d1d473387bb082e8c2929c

unckleg avatar May 07 '23 21:05 unckleg

Similar to above but fixed a couple of icons (function, package and others) Also with TypeScript checking:

https://gist.github.com/prcdpr/c328461847d991b2492d20220456133e

prcdpr avatar Jun 30 '23 15:06 prcdpr

Updated icons.all.ts for TypeScript: https://gist.github.com/Alecton4/66c9eee74ad94d463523a8dfb65f6a01

Alecton4 avatar Sep 28 '23 10:09 Alecton4

Tool to dynamically generate icon list (Change file path according to your needs)

All you need beside generated file is global.d.ts somewhere with

declare module '@elastic/eui/es/components/icon/*';

And in main.tsx

import 'icons/icons'

leaftail1880 avatar Nov 07 '23 18:11 leaftail1880