README.md in importmap-rails-0.7.6 vs README.md in importmap-rails-0.8.0

- old
+ new

@@ -108,32 +108,50 @@ ```ruby pin "react", to: "https://cdn.skypack.dev/react" ``` -## What if I don't like to use a JavaScript CDN? +## Downloading vendor files from the JavaScript CDN -You always have the option to simply download the compiled JavaScript packages from the CDNs, and saving them locally in your application. You can put such files in app/javascript/vendor, and then reference them with local pins, like: +If you don't want to use a JavaScript CDN in production, you can also download vendored files from the CDN when you're setting up your pins: +```bash +./bin/importmap pin react --download +Pinning "react" to vendor/react.js via download from https://ga.jspm.io/npm:react@17.0.2/index.js +Pinning "object-assign" to vendor/object-assign.js via download from https://ga.jspm.io/npm:object-assign@4.1.1/index.js +``` + +This will produce pins in your `config/importmap.rb` like so: + ```ruby -# config/importmap.rb -pin "react", to: "vendor/react@17.0.2.js" +pin "react", to: "vendor/react.js" # https://ga.jspm.io/npm:react@17.0.2/index.js +pin "object-assign", to: "vendor/object-assign.js" # https://ga.jspm.io/npm:object-assign@4.1.1/index.js ``` -But using a JavaScript CDN is fast, secure, and easier to deal with. Start there. +The packages are downloaded to `app/javascript/vendor`, which you can check into your source control, and they'll be available through your application's own asset pipeline serving. +If you later wish to remove a downloaded pin, you again pass `--download`: +```bash +./bin/importmap unpin react --download +Unpinning and removing "react" +Unpinning and removing "object-assign" +``` + +Just like with a normal pin, you can also update a pin by running the `pin --download` command again. + + ## Preloading pinned modules -To avoid the waterfall effect where the browser has to load one file after another before it can get to the deepest nested import, we use [modulepreload links](https://developers.google.com/web/updates/2017/12/modulepreload). Pinned modules are preloaded by default, but you can turn this off with `preload: false`. +To avoid the waterfall effect where the browser has to load one file after another before it can get to the deepest nested import, importmap-rails supports [modulepreload links](https://developers.google.com/web/updates/2017/12/modulepreload). Pinned modules can be preloaded by appending `preload: true` to the pin. Example: ```ruby # config/importmap.rb -pin "@github/hotkey", to: "https://ga.jspm.io/npm:@github/hotkey@1.4.4/dist/index.js" -pin "md5", to: "https://cdn.jsdelivr.net/npm/md5@2.3.0/md5.js", preload: false +pin "@github/hotkey", to: "https://ga.jspm.io/npm:@github/hotkey@1.4.4/dist/index.js", preload: true +pin "md5", to: "https://cdn.jsdelivr.net/npm/md5@2.3.0/md5.js" # app/views/layouts/application.html.erb <%= javascript_importmap_tags %> # will include the following link before the importmap is setup: @@ -151,12 +169,12 @@ # my_engine/lib/my_engine/engine.rb module MyEngine class Engine < ::Rails::Engine # ... - initializer "my-engine.importmap" do |app| - app.config.importmap.draw(Engine.root.join("config/importmap.rb")) + initializer "my-engine.importmap", after: "importmap" do |app| + app.importmap.draw(Engine.root.join("config/importmap.rb")) end end end ``` @@ -180,16 +198,27 @@ ``` ## Sweeping the cache in development and test -Generating the import map json and modulepreloads may require resolving hundreds of assets. This can take a while, so these operations are cached, but in development and test, we watch for changes to both `config/importmap.rb` and files in `app/javascript` to clear this cache. This feature can be controlled in an environment configuration file via the boolean `config.importmap.sweep_cache`. If you're pinning local files from outside of `app/javascript`, you'll need to restart your development server upon changes to those external files. +Generating the import map json and modulepreloads may require resolving hundreds of assets. This can take a while, so these operations are cached, but in development and test, we watch for changes to both `config/importmap.rb` and files in `app/javascript` to clear this cache. This feature can be controlled in an environment configuration file via the boolean `config.importmap.sweep_cache`. +If you're pinning local files from outside of `app/javascript`, you'll need to add them to the cache sweeper configuration or restart your development server upon changes to those external files. To add them to the configuration to clear the cache on changes, for instance when locally developing an engine, use an initializer like the following sample `config/initializers/importmap-caching.rb`: +```ruby +if Rails.env.development? + Rails.application.importmap.cache_sweeper watches: [ + Rails.application.root.join("app/javascript"), + MyEngine::Engine.root.join("app/assets/javascripts"), + ] +end +``` + ## Expected errors from using the es-module-shim While import maps are native in Chrome and Edge, they need a shim in other browsers that'll produce a JavaScript console error like `TypeError: Module specifier, 'application' does not start with "/", "./", or "../".`. This error is normal and does not have any user-facing consequences. +In Firefox. when opening the browser console, the asm.js module lexer build will run in unoptimized mode due to the debugger attaching. This gives a warning message `"asm.js type error: Disabled because no suitable wasm compiler is available"` which is as expected. When the console is closed again, the asm.js optimizations are fully applied, and this can even be verified with the console open by disabling the debugger in `about:config` and reloading the page. ## Turning off the shim Under certain circumstances, like running system tests using chromedriver under CI (which may be resource constrained and trigger errors in certain cases), you may want to explicitly turn off including the shim. You can do this by calling the bulk tag helper with `javascript_importmap_tags("application", shim: false)`. Thus you can pass in something like `shim: !ENV["CI"]`. If you want, and are sure you're not doing any full-page caching, you can also connect this directive to a user agent check (using a gem like `useragent`) to check whether the browser is chrome/edge 89+. But you really shouldn't have to, as the shim is designed to gracefully work with natively compatible drivers.