Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Vite/Rollup/ESBuild cannot process the dynamic imports in EuiIcon #5463

Open
Tracked by #7630
balthild opened this issue Dec 11, 2021 · 24 comments
Open
Tracked by #7630

Vite/Rollup/ESBuild cannot process the dynamic imports in EuiIcon #5463

balthild opened this issue Dec 11, 2021 · 24 comments
Labels
task A task associated with a larger Meta issue

Comments

@balthild
Copy link

balthild commented Dec 11, 2021

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
Copy link
Author

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')
+};

@cee-chen
Copy link
Contributor

cee-chen commented Dec 14, 2021

Thanks for finding this @balthild! For context, I removed the concatenated .js extension in #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 🙈

@balthild
Copy link
Author

balthild commented Dec 19, 2021

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.

@cee-chen
Copy link
Contributor

cee-chen commented Dec 20, 2021

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

@henry-young
Copy link

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.

@TomSoldier
Copy link

TomSoldier commented Apr 22, 2022

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?

@henry-young
Copy link

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.

@TomSoldier
Copy link

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.

@cee-chen
Copy link
Contributor

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!

@TomSoldier
Copy link

TomSoldier commented Apr 25, 2022

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.

@cee-chen
Copy link
Contributor

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.

@badwulfy
Copy link

badwulfy commented Jul 12, 2022

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

@thompsongl
Copy link
Contributor

thompsongl commented Jul 12, 2022

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.

@jgentes
Copy link

jgentes commented Aug 15, 2022

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

@j-m
Copy link
Contributor

j-m commented Jan 26, 2023

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)

@lightwave
Copy link

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.

@henry-young
Copy link

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.

@lightwave
Copy link

@henry-young Thanks! That works perfectly.

@unckleg
Copy link

unckleg commented May 7, 2023

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

@prcdpr
Copy link

prcdpr commented Jun 30, 2023

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

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

@Alecton4
Copy link

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

@cee-chen cee-chen changed the title Vite/Rollup cannot process the dynamic imports in EuiIcon Vite/Rollup/ESBuild cannot process the dynamic imports in EuiIcon Oct 9, 2023
@leaftail1880
Copy link

leaftail1880 commented Nov 7, 2023

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'

@JasonStoltz JasonStoltz added the task A task associated with a larger Meta issue label Mar 28, 2024
@lpkobamn
Copy link

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'

thanks!

@tstojecki
Copy link

We've migrated to vite as a result of moving to dotnet 9, which is now using vite for its default client templates.
The approach with copying all icon imports into a file, or including the ones used in code + where part of any built-in components, is definetely not ideal.

Also, with the workaround of including all icons imports and adding to cache, can somebody comment on impact on both dev and prod bundle size?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
task A task associated with a larger Meta issue
Projects
None yet
Development

No branches or pull requests