如何在 Rails 7 引擎中设置 importmap-rails?
How to set up importmap-rails in Rails 7 engine?
我已经在 importmap-rails gem github 存储库 here 中提出了一个关于这个的问题,但我想我会把这个问题抛在这里以防万一可能有解决方法
这是我目前的发现
使用 rails plugin new custom_page --mountable --full
生成的 Rails 7 alpha 2 或 Rails 7.0 的新引擎生成包含 importmap-rails gem 在捆绑的 gem 中,但无法使用它。将 spec.add_dependency 'importmap-rails'
添加到 enginename.gemspec 没有区别,将 require importmap-rails
添加到 engine.rb 也没有区别。 bin 目录中没有 importmap 可执行文件。
致电 bundle info importmap-rails
产生一个有希望的结果,表明 gem 默认安装
* importmap-rails (0.8.1)
Summary: Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling.
Homepage: https://github.com/rails/importmap-rails
Source Code: https://github.com/rails/importmap-rails
Path: /home/jamie/.rvm/gems/ruby-3.0.0@custom_page/gems/importmap-rails-0.8.1
调用 rails --tasks
显示
rails app:importmap:install # Setup Importmap for the app
但我相信这是来自 --full 选项生成的测试应用程序,而不是可用于引擎的 rails 命令。
我期待在没有应用程序的情况下看到相同的内容:前缀
对此任务的调用解析为模板错误,如图所示
rails app:importmap:install
Don't know how to build task 'app:template' (See the list of available
tasks with rails --tasks
) Did you mean? app:tmp:create
如果有解决此问题的解决方案,我将不胜感激,我相信其他人也会。我想要这个的原因是我完全没有在 rails 6.1.4 引擎中引入 webpacker,我希望这将是我的,大大改进的解决方案
我回到老派 Javascript 包含在 html 中。
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js"></script>
嗯,它绝对适用于所有浏览器,而不是确定浏览器是否支持我以后可能会使用的功能。
我也可以完全控制要放置哪个页面...但这可能不是您想要的...
您不需要使用安装任务来设置导入映射。它所做的只是一些复制粘贴操作,无论如何它对引擎设置没有真正帮助。
将 importmap 添加到引擎的 gemspec 文件:
# my_engine/my_engine.gemspec
spec.add_dependency "importmap-rails"
更新engine.rb:
# my_engine/lib/my_engine/engine.rb
require "importmap-rails"
module MyEngine
class Engine < ::Rails::Engine
isolate_namespace MyEngine
initializer "my-engine.importmap", before: "importmap" do |app|
# NOTE: this will add pins from this engine to the main app
# https://github.com/rails/importmap-rails#composing-import-maps
app.config.importmap.paths << root.join("config/importmap.rb")
# NOTE: something about cache; I did not look into it.
# https://github.com/rails/importmap-rails#sweeping-the-cache-in-development-and-test
app.config.importmap.cache_sweepers << root.join("app/assets/javascripts")
end
# NOTE: add engine manifest to precompile assets in production
initializer "my-engine.assets" do |app|
app.config.assets.precompile += %w[my_engine_manifest]
end
end
end
更新资产清单:
# my_engine/app/assets/config/my_engine_manifest.js
//= link_tree ../javascripts/my_engine .js
如果需要,为我们的引擎添加 javascript 入口点。 Pin 图将在没有此文件的情况下可用。
# my_engine/app/assets/javascripts/my_engine/application.js
// do some javascript
document.querySelector("h1").innerText = "hi, i'm your engine";
console.log("hi, again");
更新引擎的布局:
# my_engine/app/views/layouts/my_engine/application.html.erb
<!DOCTYPE html>
<html>
<head>
<%#
NOTE: This loads/imports main app 'application.js' and all the pins from
the main app and from the engine (because we set it up in the engine.rb).
%>
<%= javascript_importmap_tags %>
<%#
NOTE: Too add engine's javascript functionality we have to load the
entrypoint here or `import` it in the main app `application.js`
%>
<%= javascript_import_module_tag "my_engine/application" %>
</head>
<body> <%= yield %> </body>
</html>
创建 importmap.rb 并固定 my_engine/application
,此名称必须与 javascript_import_module_tag
匹配。它不能与主应用程序中的任何其他名称冲突,因此您不能只使用 application
:
# my_engine/config/importmap.rb
# NOTE: this pin works because `my_engine/app/assets/javascripts
# is in the `Rails.application.config.assets.paths`
pin "my_engine/application"
一些额外的测试设置:
# app/config/routes.rb
Rails.application.routes.draw do
mount MyEngine::Engine => "/"
end
# my_engine/config/routes.rb
MyEngine::Engine.routes.draw do
get 'home', to: 'homes#index'
end
# my_engine/app/controllers/my_engine/homes_controller.rb
module MyEngine
class HomesController < ApplicationController
def index; end
end
end
# my_engine/app/views/my_engine/homes/index.html.erb
<h1>Home</h1>
此时,您应该在呈现的布局的 <head>
标记中包含此内容,其中包括:
<script type="importmap" data-turbo-track="reload">{
"imports": {
"application": "/assets/application-66ce7505c61e3e4910ff16e7c220e1fbfb39251cd82e4bab8d325b3aae987cf9.js",
"my_engine/application": "/assets/my_engine/application-31ce493e8376b4c20703a50f38d419ae309ffe410b7ab7fec47440e02eef08a8.js",
}
}</script>
<script type="module">import "application"</script>
<script type="module">import "my_engine/application"</script>
H1
标签在重新加载时应更改为 <h1>hi, i'm your engine</h1>
。
可以使用 https://generator.jspm.io/ 手动添加其他导入映射。
为了加分,bin/importmap
可以定制为在引擎内部工作。在 bin 目录中创建一个新的 importmap
文件。
# my_engine/bin/importmap NOTE: don't forget to `chmod u+x bin/importmap` to make it executable.
#!/usr/bin/env ruby
# NOTE: make sure we are loading the correct versions of things
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
# NOTE: importmap requires some rails goodness that we don't have in the engine,
# because we don't have config/application.rb that loads the environment.
require "rails"
# importmap-rails is not loaded automatically
require "importmap-rails"
# the actual command runner
require "importmap/commands"
运行 来自引擎目录:
$ bin/importmap pin react
Pinning "react" to https://ga.jspm.io/npm:react@18.1.0/index.js
$ cat config/importmap.rb
pin "my_engine/application"
pin "react", to: "https://ga.jspm.io/npm:react@18.1.0/index.js"
我没有对其进行太多测试,因此欢迎任何反馈。如果没有显示,请重新启动服务器,我不知道重新加载如何处理所有这些。
我已经在 importmap-rails gem github 存储库 here 中提出了一个关于这个的问题,但我想我会把这个问题抛在这里以防万一可能有解决方法
这是我目前的发现
使用 rails plugin new custom_page --mountable --full
生成的 Rails 7 alpha 2 或 Rails 7.0 的新引擎生成包含 importmap-rails gem 在捆绑的 gem 中,但无法使用它。将 spec.add_dependency 'importmap-rails'
添加到 enginename.gemspec 没有区别,将 require importmap-rails
添加到 engine.rb 也没有区别。 bin 目录中没有 importmap 可执行文件。
致电 bundle info importmap-rails
产生一个有希望的结果,表明 gem 默认安装
* importmap-rails (0.8.1)
Summary: Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling.
Homepage: https://github.com/rails/importmap-rails
Source Code: https://github.com/rails/importmap-rails
Path: /home/jamie/.rvm/gems/ruby-3.0.0@custom_page/gems/importmap-rails-0.8.1
调用 rails --tasks
显示
rails app:importmap:install # Setup Importmap for the app
但我相信这是来自 --full 选项生成的测试应用程序,而不是可用于引擎的 rails 命令。 我期待在没有应用程序的情况下看到相同的内容:前缀 对此任务的调用解析为模板错误,如图所示
rails app:importmap:install
Don't know how to build task 'app:template' (See the list of available tasks with
rails --tasks
) Did you mean? app:tmp:create
如果有解决此问题的解决方案,我将不胜感激,我相信其他人也会。我想要这个的原因是我完全没有在 rails 6.1.4 引擎中引入 webpacker,我希望这将是我的,大大改进的解决方案
我回到老派 Javascript 包含在 html 中。
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js"></script>
嗯,它绝对适用于所有浏览器,而不是确定浏览器是否支持我以后可能会使用的功能。
我也可以完全控制要放置哪个页面...但这可能不是您想要的...
您不需要使用安装任务来设置导入映射。它所做的只是一些复制粘贴操作,无论如何它对引擎设置没有真正帮助。
将 importmap 添加到引擎的 gemspec 文件:
# my_engine/my_engine.gemspec
spec.add_dependency "importmap-rails"
更新engine.rb:
# my_engine/lib/my_engine/engine.rb
require "importmap-rails"
module MyEngine
class Engine < ::Rails::Engine
isolate_namespace MyEngine
initializer "my-engine.importmap", before: "importmap" do |app|
# NOTE: this will add pins from this engine to the main app
# https://github.com/rails/importmap-rails#composing-import-maps
app.config.importmap.paths << root.join("config/importmap.rb")
# NOTE: something about cache; I did not look into it.
# https://github.com/rails/importmap-rails#sweeping-the-cache-in-development-and-test
app.config.importmap.cache_sweepers << root.join("app/assets/javascripts")
end
# NOTE: add engine manifest to precompile assets in production
initializer "my-engine.assets" do |app|
app.config.assets.precompile += %w[my_engine_manifest]
end
end
end
更新资产清单:
# my_engine/app/assets/config/my_engine_manifest.js
//= link_tree ../javascripts/my_engine .js
如果需要,为我们的引擎添加 javascript 入口点。 Pin 图将在没有此文件的情况下可用。
# my_engine/app/assets/javascripts/my_engine/application.js
// do some javascript
document.querySelector("h1").innerText = "hi, i'm your engine";
console.log("hi, again");
更新引擎的布局:
# my_engine/app/views/layouts/my_engine/application.html.erb
<!DOCTYPE html>
<html>
<head>
<%#
NOTE: This loads/imports main app 'application.js' and all the pins from
the main app and from the engine (because we set it up in the engine.rb).
%>
<%= javascript_importmap_tags %>
<%#
NOTE: Too add engine's javascript functionality we have to load the
entrypoint here or `import` it in the main app `application.js`
%>
<%= javascript_import_module_tag "my_engine/application" %>
</head>
<body> <%= yield %> </body>
</html>
创建 importmap.rb 并固定 my_engine/application
,此名称必须与 javascript_import_module_tag
匹配。它不能与主应用程序中的任何其他名称冲突,因此您不能只使用 application
:
# my_engine/config/importmap.rb
# NOTE: this pin works because `my_engine/app/assets/javascripts
# is in the `Rails.application.config.assets.paths`
pin "my_engine/application"
一些额外的测试设置:
# app/config/routes.rb
Rails.application.routes.draw do
mount MyEngine::Engine => "/"
end
# my_engine/config/routes.rb
MyEngine::Engine.routes.draw do
get 'home', to: 'homes#index'
end
# my_engine/app/controllers/my_engine/homes_controller.rb
module MyEngine
class HomesController < ApplicationController
def index; end
end
end
# my_engine/app/views/my_engine/homes/index.html.erb
<h1>Home</h1>
此时,您应该在呈现的布局的 <head>
标记中包含此内容,其中包括:
<script type="importmap" data-turbo-track="reload">{
"imports": {
"application": "/assets/application-66ce7505c61e3e4910ff16e7c220e1fbfb39251cd82e4bab8d325b3aae987cf9.js",
"my_engine/application": "/assets/my_engine/application-31ce493e8376b4c20703a50f38d419ae309ffe410b7ab7fec47440e02eef08a8.js",
}
}</script>
<script type="module">import "application"</script>
<script type="module">import "my_engine/application"</script>
H1
标签在重新加载时应更改为 <h1>hi, i'm your engine</h1>
。
可以使用 https://generator.jspm.io/ 手动添加其他导入映射。
为了加分,bin/importmap
可以定制为在引擎内部工作。在 bin 目录中创建一个新的 importmap
文件。
# my_engine/bin/importmap NOTE: don't forget to `chmod u+x bin/importmap` to make it executable.
#!/usr/bin/env ruby
# NOTE: make sure we are loading the correct versions of things
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
# NOTE: importmap requires some rails goodness that we don't have in the engine,
# because we don't have config/application.rb that loads the environment.
require "rails"
# importmap-rails is not loaded automatically
require "importmap-rails"
# the actual command runner
require "importmap/commands"
运行 来自引擎目录:
$ bin/importmap pin react
Pinning "react" to https://ga.jspm.io/npm:react@18.1.0/index.js
$ cat config/importmap.rb
pin "my_engine/application"
pin "react", to: "https://ga.jspm.io/npm:react@18.1.0/index.js"
我没有对其进行太多测试,因此欢迎任何反馈。如果没有显示,请重新启动服务器,我不知道重新加载如何处理所有这些。