Similar to the Webpack Bundle Analyzer, Chrome's new Lighthouse feature …
… shows a visualisation of your JavaScript bundles. It's compatible with sourcemaps and is great for understanding large JavaScript modules used by your page. It can also visualise unused bytes.
This is very helpful to visualize Javascript files in development. It also works on production code, where its usefulness depends on the structure of the productive Javascr...
From Exploring ES6:
Module imports are hoisted (internally moved to the beginning of the current scope). Therefore, it doesn’t matter where you mention them in a module and the following code works without any problems:
foo(); import { foo } from 'my_module';
When you're not aware of import hoisting you may be surprised that your code runs in a different order than you see in the source file.
The example below is taken from the [...
Jasmine is a great way to unit test your JavaScript components without writing an expensive end-to-end test for every small requirement.
After we integrated Jasmine into a Rails app we often add an E2E test that opens that Jasmine runner and expects all specs to pass. This way we see Jasmine failures in our regular test runs.
In a [feature spec](https://relishapp.com/rspec/rspec-rails/docs/feature-spec...
A flaky test is a test that is often green, but sometimes red. It may only fail on some PCs, or only when the entire test suite is run.
There are many causes for flaky tests. This card focuses on a specific class of feature with heavy side effects, mostly on on the UI. Features like the following can amplify your flakiness issues by unexpectedly changing elements, causing excessive requests or other timing issues:
You want to use <input type="number">
fields in your applications.
However, your desktop users may encounter some weird quirks:
to_i
in Ruby) you'll end up with wrong values (like 1 instead o...Event delegation is a pattern where a container element has a single event listener that handles events for all descendants that match a CSS selector.
This pattern was popularized by jQuery that lets you do this:
$('.container').on('click', '.message', function(event) {
console.log("A message element was clicked!")
})
This technique has some advantages:
Most browsers have built-in drag and drop support for different page elements like text and images. While this may be useful in most situations, it may become annoying in others. If you e.g. want to allow the user to scroll/move horizontally within a container by grabbing an item and moving the mouse, you will notice that nothing will move and you'll instead start dragging that element.
To disable this, add the following CSS to your content:
-webkit-user-drag: none
user-drag: none
-webkit-user-drag
is only fully supported in ...
Rails has the handy controller method send_file which lets us download files easily. We can decide whether the file should be downloaded (disposition: 'attachment'
) or shown in the browser (disposition: 'inline'
). The default is disposition: 'attachment'
.
Downloading files will not work when you are calling the controller action from an AJAX request. The browser will try to render the file and insert it in the DOM, which is never what you want.
Unpoly (sin...
It is generally discouraged to load your JavaScript by a <script src>
tag in the <head>
:
<head>
<script src="app.js"></script>
</head>
The reason is that a <script src>
tag will pause the DOM parser until the script has loaded and executed. This will delay the browser's first contentful paint.
A much better default is to load your scripts with a <script src defer>
tag:
<head>
<script src="app.js" defer></script>
</head>
A deferred script has many useful properties:
The attached compiler()
function below applies JavaScript behavior to matching HTML elements as they enter the DOM.
This works like an Unpoly compiler for apps that don't use Unpoly, Custom Elements or any other mechanism that pairs JavaScript with HTML elements.
The compiler()
function is also a lightweight replacement for our legacy [$.unobtrusive()
](https://makandracards.com/makandra/4-unobtrusiv...
Given you have a strict CSP that only allows <script src>
elements from your own domain:
Content-Security-Policy: script-src 'self'
This will block JavaScript handlers inlined as attribute into your HTML elements. Clicking on the following link will only log an error with a strict CSP:
<a href="javascript:alert('hello')">click me</a>
<a href="#" onclick="alert('hello')">click me</a>
The recommended solution is to move the handler from the HTML to the allowed ...
Often people need links which are not linked directly, but should trigger execution of javascript.
You can find a lot of workarounds for that:
<a href="#">Do something with js!</a>
This defines an empty anchor. This may lead the browser to let the page jump to the top when the link is clicked, unless you call preventDefault
on the event. This is probably not what you want.
<a href="#!">Do something with js!</a>
This tells the browser to jump to an anchor !
. It depends on the browser implementation what happens when an anc...
You can scale background images in CSS to the container size using background-size
(Demo).
Commonly, we use contain
or cover
because we want to preserve the image's aspect ratio.
If you do not want to do that, simply provide scaling values for X and Y:
background-size: 100% 100%
(a simple 100%
would mean 100% auto
and respect the image's aspect ratio)
The above may not work for you when ...
After switching a project from Sprockets to Webpack, I started observing a bug that was hard to debug: Our custom icon font could sometimes not be displayed until a full page reload.
Digging deeper the only difference before and after the page load was the encoding interpretation of the iconfont stylesheet:
Correct representation (UTF-8):
.icon:before {
content: ""
}
Broken representation (other charset):
`...
When testing JavaScript functionality in Selenium (E2E), you may need to access a class or function inside of a evaluate_script
block in one of your steps. Capybara may only access definitions that are attached to the browser (over the window
object that acts as the base). That means that once you are exporting your definition(s) in Webpacker, these won't be available in your tests (and neither in the dev console). The following principles/concepts also apply to Sprockets.
Say we have a StreetMap
class:
// street_map.js
class S...
When a Ruby version gem has a letter in its version number, it is considered a pre-release:
1.0.0.rc1
2.3.0.alpha2
3.0.0.beta3
4.0.0.pre.rc2
Even if a pre-release gem has the highest version number, it is never installed unless the user explictily requested the version:
gem install foobar --version="=2.3.0.alpha2"
Also bundle update
will never update a stable version to a pre-release version unless the user explicitly requests it in the Gemfile
:
gem 'foobar', '=2.3.0.alpha2'
A note on Semanti...
In RubyMine folders can be excluded from search, navigation etc. by marking it as excluded. You might sometimes wish to exclude single files, too. An example could be .byebug_history
which is located in the project root directory.
Single files can be excluded by pattern in the Settings:
Ctrl+Alt+S
, go to Project structure
If your Webpack build is slow, you can use the Speed Measure Plugin for Webpack to figure out where time is being spent.
Note that at time of writing, Webpack 5 seems unsupported. It works on Webpack 4, though.
Wire it into your application as described in the library's documentation:
config/webpack/development.js
and instead of exporting your Webpack config
,...Sometimes you want to load code on demand. For instance, when a a large library is only used on a single screen, this library should only be loaded for that screen. It should not blow up the bundle size for all screens.
You can load code on demand by using import()
as a function (with parentheses) instead of using it as a keyword import
(without parentheses). The import()
function returns a promise with the exported variables:
let exports = await import('large-library')
console.log("A named export is ", exports.exportedName)
c...
Webpack builds can take a long time, so we only want to compile when needed.
This card shows what will cause Webpacker (the Rails/Webpack integration) to compile your assets.
While development it is recommended to boot a webpack dev server using bin/webpack-dev-server
.
The dev server compiles once when booted. When you access your page on localhost
before the initial compilation, the page may load without assets.
The ...
I use the TypeScript compiler for this, since its output is more minimal than Babel's.
The following will transpile all src/*.js
files into a file build.js
:
npm install typescript
npx tsc src/*.js --target ES5 --allowJs --outFile build.js
The output will only transpile ES6 syntax. It will not include any polyfills for missing APIs.
When your Rails application server raises error, Capybara will fail your test when it clears the session after the last step. The effect is a test that passes all steps, but fails anyway.
Capybara's behavior will help you to detect and fix errors in your application code. However, sometimes your application will explode with an error outside your control. Two examples:
Browsers blocks abusable JavaScript API calls until the user has interacted with the document. Examples would be opening new tab or start playing video or audio.
E.g. if you attempt to call video.play()
in a test, the call will reject with a message like this:
NotAllowedError: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD
To pretend document interaction in a test you can create an element, click on it, and remove the element again. This unblocks the entire JavaSc...
capybara-lockstep can help you with flaky end-to-end tests:
This Ruby gem synchronizes Capybara commands with client-side JavaScript and AJAX requests. This greatly improves the stability of a full-stack integration test suite, even if that suite has timing issues.