Tag: Applications

Responsible Web Applications

Joy Heron bought a cool domain name and published an article there:

Luckily, with modern HTML and CSS, we can create responsive and accessible web apps with relative ease. In my years of doing software development, I have learned some HTML and CSS tips and tricks, and I want to present these in this post. This list is not exhaustive, but these are tried and true patterns that I frequently use in different projects.

Sure, it’s a collection of tips and tricks, but it’s a great one that covers modern best practices across HTML, CSS, and JavaScript. If someone asked me what they should read if they missed out on the last, say, three years of front-end and wanted to remind themselves of the important stuff, I’d send them this.

I like the casual use of a massive shape-outside in the header.

Direct Link to ArticlePermalink


The post Responsible Web Applications appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

,

CSS Architecture for Modern JavaScript Applications

There is a lot to like from Mike Riethmuller here:

  • The title. When you’re building a website from JavaScript-powered components anyway, that is a moment to talk about how to do styling, because it opens some doors to JavaScript-powered styles that you probably wouldn’t otherwise choose.
  • The personal experience and pragmatism. Drawing on five years of consulting, he’s seeing that component re-use and style understandability is suffering, not improving, partly due to every team having different approaches. He says “it’s a little bit of everybody’s fault” and sees the perspective of others who like parts of what JavaScript-powered styles can bring, like less dependence on specificity.
  • The fresh thinking. Since JavaScript-powered websites are all built by nested components anyway, why not use that architecture for styling? The thesis of the article is really about building UI components that, on purpose, don’t involve application logic but exist just for styling, and using a combination of clever CSS and JavaScript power to the kind of styling you need.

Direct Link to ArticlePermalink

The post CSS Architecture for Modern JavaScript Applications appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Recipes for Performance Testing Single Page Applications in WebPageTest

WebPageTest is an online tool and an Open Source project to help developers audit the performance of their websites. As a Web Performance Evangelist at Theodo, I use it every single day. I am constantly amazed at what it offers to the web development community at large and the web performance folks particularly — for free.

But things can get difficult pretty quickly when dealing with Single Page Applications — usually written with React, Vue, Svelte or any other front-end framework. How can you get through a log in page? How can you test the performance of your users’ flow, when most of it happens client-side and does not have a specific URL to point to?

Throughout this article, we are going to find out how to solve these problems (and many more), and you’ll be ready to test the performance of your Single Page Application with WebPageTest!

Note: This articles requires an intermediate understanding about some of WebPageTest advanced features.

If you are curious about web performance and want a good introduction to WebPageTest, I would highly recommend the following resources:

The problem with testing Single Page Applications

Single Page Applications (SPAs) radically changed the way websites work. Instead of letting the back end (e.g. Django, Rails and Laravel) do most of the grunt work and delivering “ready-to-use” HTML to the browser, SPAs rely heavily on JavaScript to have the browser compute HTML. Such front-end frameworks include React, Vue, Angular or Svelte.

The simplicity of WebPageTest is what makes part of its appeal to developers: head to http://webpagetest.org/easy, enter your URL, wait a little, and voilà! Your performance audit is ready.

If you are building an SPA and want to measure its performance, you could rely on end-to-end testing tools like Selenium, Cypress or Puppeteer. However, I have found that none of these has the amount of performance-related information and easy-to-use tooling that WebPageTest offers.

But testing SPAs with WebPageTest can be complex.

In many SPAs, most of the site is protected behind a log in form. I often use Netlify for hosting my sites (including my personal blog), and most of the time I spend in the application is on authenticated pages, like the dashboard listing all my websites. As the information on my dashboard is specific to me, any other user trying to access https://app.netlify.com/teams/phacks/sites is not going to see my dashboard, but will instead be redirected to either a login or 404 page.

The same goes for WebPageTest. If I enter my dashboard URL into http://webpagetest.org/easy, the audit will be performed against the login page.

Moreover, testing and monitoring the performance of dynamic interactions in SPAs cannot be achieved with simple WebPageTest audits.

Here’s an example. Nuage is a domain name registrar with fancy animations and a beautiful, dynamic interface. When you search for domain names to buy, an asynchronous call fetches the results of the request and the results are displayed as they are retrieved.

As you might have noticed in the video above, the URL of the page does not change as I type my search terms. As a consequence, it is not possible to test the performance of the search experience using a simple WebPageTest audit as we do not have a proper URL to point to the action of searching something — only to an empty search page.

Some other problems can arise from the SPA paradigm shift when using WebPageTest:

  • Clicking around to navigate a webpage is usually harder than merely heading to a new URL, but it is sometimes the only option in SPAs.
  • Authentication in SPAs is usually implemented using JSON Web Tokens instead of good ol’ cookies, which rules out the option of setting authentication cookies directly in WebPageTest (as described here).
  • Using React and Redux (or other application state management libraries) for your SPA can mean that forms are harder to fill out programmatically, since using .innerText() or .value() to set a field’s value may not forward it to the application store.
  • As API calls are often asynchronous and various loaders can be used to indicate a loading state, those can “trick” WebPageTest into believing the page has actually finished loading when it has, in fact, not. I have seen it happen with longer-than-usual API calls (5+ seconds).

As I have faced these problems on several projects, I have come up with a range of tips and techniques to counter them.

The many ways of selecting an element

Selecting DOM elements is a key part of doing all sorts of automated testing, be it for end-to-end testing with Selenium or Cypress or for performance testing with WebPageTest. Selecting DOM elements allows us to click on links and buttons, fill in forms and more generally interact with the application.

There are several ways of selecting a particular DOM elements using native browser APIs, that range from the straightforward document.getElementsByClassName to the thorny but really powerful XPath selectors. In this section, we will see three different possibilities, ordered by increasing complexity.

Get an element by id, className or tagName

If the element you want to select (say, an “Empty Cart” button) has a specific and unique id (e.g. #empty-cart), class name, or is the only button on the page, you can click on it using the getElementsBy methods:

const emptyCartButton = document.getElementsById("empty-cart")[0]; // or document.getElementsByClassName(".empty-cart-button")[0] // or document.getElementsByTagName("button")[0] emptyCartButton.click();

If you have several buttons on the same page, you can filter the resulting list before interacting with the element:

const buttons = document.getElementsByTagName("button"); const emptyCartButton = buttons.filter(button =>   button.innerText.includes("Empty Cart") )[0]; emptyCartButton.click();

Use complex CSS selectors

Sometimes, the particular element you want to interact with does not present an interesting unicity property in either its ID, class or tag.

One way to circumvent this issue is to add this unicity manually, for testing purposes only. Adding #perf-test-empty-cart-button to a specific button is innocuous for your website markup and can dramatically simplify your testing setup.

However, this solution can sometimes be out of reach: you may not have access to the source code of the application, or may not be able to deploy new versions quickly. In those situations, it is useful to know about document.querySelector (and its variant document.querySelectorAll) and using complex CSS selectors.

Here are a few examples of what can be achieved with document.querySelector:

// Select the first input with the `name="username"` property document.querySelector("input[name='username']"); // Select all number inputs document.querySelectorAll("input[type='number']");  // Select the first h1 inside the <section> document.querySelector("section h1");  // Select the first direct descendent of a <nav> which is of type <img> document.querySelector("nav > img");

What’s interesting here is you have the full power of CSS selectors at hand. I encourage you to have a look at the always-useful MDN’s reference table of selectors!

Going nuclear: XPath selectors

XML Path Language (XPath), albeit really powerful, is harder to grasp and maintain than the CSS solutions above. I rarely have to use it, but it is definitively useful to know that it exists.

One such instance is when you want to select a node by its text value, and can’t resort to CSS selectors. Here’s a handy snippet to use in those cases:

// Returns the  that has the exact content 'Sep 16, 2015' document.evaluate(   "//span[text()='Sep 16, 2015']",   document,   null,   XPathResult.FIRST_ORDERED_NODE_TYPE,   null ).singleNodeValue;

I will not go into details on how to use it as it would have me wander away from the goal of this article. To be fair, I don’t even know what many of the parameters above even mean. However, I can definitely recommend the MDN documentation should you want to read on the topic.

Recipes for common use cases

In the following section, we will see how to test the performance in common use cases of Single Page Applications. I call these my testing recipes.

In order to illustrate those recipes, I will use the React Admin demo website as an example. React Admin is an open source project aimed at building admin applications and back offices.

It is a typical example of a SPA because it uses React (as the name suggests), calls remote APIs, has a login interface, many forms and relies on client-side routing. I encourage you to go take a quick look at the website (the demo account is demo/demo ) in order to have an idea of what we will be trying to achieve.

Authentication and forms

The authentication page of React Admin requires the user to input a username and a password:

The authentication screen of React Admin

Intuitively, one could take the following approach to filling in the form and submit:

const [usernameInput, passwordInput] = document.getElementsByTagName("input"); usernameInput.value = "demo"; // innerText could also be used here passwordInput.value = "demo"; document.getElementsByTagName("button")[0].click();

If you run these commands sequentially in a DevTools console on the login page, you will see that all fields are reset and the login request fails upon submitting by clicking the button. The problem comes from the fact that the new values we set with .value() (or .innerText()) are not kicked back to the Redux store, and thus not “processed” by the application.

What we need to do then is explicitly tell React that the value has changed so that it will update internal bookkeeping accordingly. This can be achieved using the Event interface.

const updateInputValue = (input, newValue) => {   let lastValue = input.value;   input.value = newValue;   let event = new Event("input", { bubbles: true });   let tracker = input._valueTracker;   if (tracker) {     tracker.setValue(lastValue);   }   input.dispatchEvent(event); };

Note: this solution is pretty hacky (even according to its own author), however it works well for our purposes here.

Our updated script becomes:

const updateInputValue = (input, newValue) => {   let lastValue = input.value;   input.value = newValue;   let event = new Event("input", { bubbles: true });   let tracker = input._valueTracker;   if (tracker) {     tracker.setValue(lastValue);   }   input.dispatchEvent(event); };  const [usernameInput, passwordInput] = document.getElementsByTagName("input");  updateInputValue(usernameInput, "demo"); updateInputValue(passwordInput, "demo");  document.getElementsByTagName("button")[0].click();

Hurrah! You can try it in your browser’s console—It works like a charm.

Translating this to an actual WebPageTest script (with scripting keywords, single line commands and tab-separated parameters) would look like this:

setEventName    Go to Login  navigate    https://marmelab.com/react-admin-demo/  setEventName    Login      exec    const updateInputValue = (input, newValue) => {  let lastValue = input.value;  input.value = newValue;  let event = new Event("input", { bubbles: true });  let tracker = input._valueTracker;  if (tracker) {  tracker.setValue(lastValue);  }  input.dispatchEvent(event);};  exec    const [usernameInput, passwordInput] = document.getElementsByTagName("input")  exec    updateInputValue(usernameInput, "demo") exec    updateInputValue(passwordInput, "demo")  execAndWait document.getElementsByTagName("button")[0].click()

Note that clicking on the submit button leads us to a new page and triggers API calls, which means we need to use the execAndWait command.

You can see the full results of the test at this address. (Note: the results may have been archived by WebPageTest — you can, however, run the test again yourself!)

Here is a short video (captured by WebPageTest) in which you can see that we indeed passed the authentication step:

Navigating between pages

For traditional Server Rendered pages, navigating from one URL to the next in WebPageTest scripting is done via the navigate <url> command.

However, for SPAs, this does not reflect the experience of the user, as client-side routing means that the server has no role in navigation. Thus, hitting a URL directly would significantly slow down the measured performance (because of the time it takes for the JavaScript framework to be compiled, parsed and executed), a slowdown that the user does not experience when changing pages. As it is crucial to simulate the user flow the best we can, we need to handle the navigation on the client as well.

Hopefully, this is a lot simpler to do than filling up forms. We only need to select the link (or button) that will take us to the new page, and .click() on it! Let’s follow through our previous example, although now we want to test the performance of the Reviews list, and of a single Review page.

A user would typically click on the Reviews item on the left-hand navigation menu, then on any item in the list. Inspecting the elements in DevTools may lead us to a selection strategy as follows:

document.querySelector("a[href='#reviews']"); // select the Reviews link in the menu document.querySelector("table tr"); // select the first item in the Reviews list

As both clicks lead to page transition and API calls (to fetch the reviews), we need to use the execAndWait keyword for the script:

setEventName    Go to Login  navigate    https://marmelab.com/react-admin-demo/  setEventName    Login  exec    const updateInputValue = (input, newValue) => {  let lastValue = input.value;  input.value = newValue;  let event = new Event("input", { bubbles: true });  let tracker = input._valueTracker;  if (tracker) {    tracker.setValue(lastValue);  }  input.dispatchEvent(event);};  exec    const [usernameInput, passwordInput] = document.getElementsByTagName("input")  exec    updateInputValue(usernameInput, "demo") exec    updateInputValue(passwordInput, "demo")  execAndWait document.getElementsByTagName("button")[0].click()  setEventName    Go to Reviews  execAndWait document.querySelector("a[href='#/reviews']").click()  setEventName    Open a single Review  execAndWait document.querySelector("table tbody tr").click()

Here’s the video of the complete script running on WebPageTest:

The audit result from WebPageTest shows the performance metrics and waterfall graphs for each step of the script, allowing us to monitor the performance of each API call and interaction:

What about Internet Explorer 11 compatibility?

WebPageTest allows us to select which location, browser and network conditions the test will use. Internet Explorer 11 (IE11) is among the available browser options, and if you try the previous scripts on IE11, they will fail.

This is due to two reasons:

The ES6 syntax problem can be overcome by translating our scripts to ES5 syntax (no arrow functions, no let and const, no array destructuring), which might look like this:

setEventName    Go to Login  navigate    https://marmelab.com/react-admin-demo/  setEventName    Login  exec    var updateInputValue = function(input, newValue) {  var lastValue = input.value;  input.value = newValue;  var event = new Event("input", { bubbles: true });  var tracker = input._valueTracker;  if (tracker) {    tracker.setValue(lastValue);  }  input.dispatchEvent(event);};  exec    var usernameInput = document.getElementsByTagName("input")[0] exec    var passwordInput = document.getElementsByTagName("input")[1]  exec    updateInputValue(usernameInput, "demo") exec    updateInputValue(passwordInput, "demo")  execAndWait document.getElementsByTagName("button")[0].click()  setEventName    Go to Reviews  execAndWait document.querySelector("a[href='#/reviews']").click()  setEventName    Open a single Review  execAndWait document.querySelector("table tbody tr").click()

In order to bypass the absence of CustomEvent support, we can turn to polyfills and add one manually at the top of the script. This polyfill is available on MDN:

(function() {   if (typeof window.CustomEvent === "function") return false;   function CustomEvent(event, params) {     params = params || { bubbles: false, cancelable: false, detail: undefined };     var evt = document.createEvent("CustomEvent");     evt.initCustomEvent(       event,       params.bubbles,       params.cancelable,       params.detail     );     return evt;   }   CustomEvent.prototype = window.Event.prototype;   window.CustomEvent = CustomEvent; })();

We can then replace all mentions of Event by CustomEvent, set the polyfill to fit on a single line and we are good to go!

setEventName    Go to Login  navigate    https://marmelab.com/react-admin-demo/  exec    (function(){if(typeof window.CustomEvent==="function")return false;function CustomEvent(event,params){params=params||{bubbles:false,cancelable:false,detail:undefined};var evt=document.createEvent("CustomEvent");evt.initCustomEvent(event,params.bubbles,params.cancelable,params.detail);return evt}CustomEvent.prototype=window.Event.prototype;window.CustomEvent=CustomEvent})();  setEventName    Login  exec    var updateInputValue = function(input, newValue) {  var lastValue = input.value;  input.value = newValue;  var event = new CustomEvent("input", { bubbles: true });  var tracker = input._valueTracker;  if (tracker) {    tracker.setValue(lastValue);  }  input.dispatchEvent(event);};  exec    var usernameInput = document.getElementsByTagName("input")[0] exec    var passwordInput = document.getElementsByTagName("input")[1]  exec    updateInputValue(usernameInput, "demo") exec    updateInputValue(passwordInput, "demo")  execAndWait document.getElementsByTagName("button")[0].click()  setEventName    Go to Reviews  execAndWait document.querySelector("a[href='#/reviews']").click()  setEventName    Open a single Review  execAndWait document.querySelector("table tbody tr").click()

Et voilà!

General tips and tricks for WebPageTest scripting

One last thing I want to do is provide a few tips and tricks that make writing WebPageTest scripts easier. Feel free to DM me on Twitter if you have any suggestions!

Security first!

Remember to tick both privacy checkboxes if your script includes senstitive data, like credentials!

WebPageTest security controls

Browse the docs

The WebPageTest Scripting docs are full of features that I didn’t cover in this article, ranging from DNS Overriding to iPhone Spoofing and even if/else conditionals.

When you plan on writing a new script, I recommend to have a look at the available parameters first and see if any can help make your scripting easier or more robust.

Long loading states

Sometimes, a remote API call (say, for fetching the reviews) will take a long time. A loading indicator, such as a spinner, can be used to tell the user to wait a bit as something is happening.

WebPageTest tries to detect when a page has finished loading by figuring out if things are changing on the screen. If your loading indicator lasts a long time, WebPageTest might mistake it for an integral part of your page design and cut the audit before the API call returns — thus truncating your measures.

A way to circumvent this issue is to tell WebPageTest to wait at least a certain duration before stopping the test. This is a parameter available under the Advanced tab:

WebPageTest minimum test duration

Keeping your script (and results) human-readable

  • Use blank lines and comments (//) generously because single-line JavaScript commands can sometimes be hard to grasp.
  • Keep a multi-line version somewhere as your reference, and single-line everything as you are about to test. This helps readability. Like, a lot.
  • Use setEventName to name your different “steps.” This makes for more readable tests as it explicits the sequence of pages the audit goes through, and also appears in the WebPageTest results.

Iterating on your scripts

  • First, make sure that your script works in the browser. To do so, strip the WebPageTest keywords (the first word of every line of your script), then copy and paste each line in the browser console to verify that everything is working as expected at every step of the way.
  • Once you are ready to submit your test to WebPageTest, do it first with very light settings: only one run, a fast browser (cough — not IE11 — cough), no network throttling, no repeat view, a well-dimensioned instance (Dulles, VA, usually has good response times). This will help you detect and correct errors way faster.

Automating your scripts

Your test script is running smoothly, and you start getting performance reports of your Single Page App. As you ship new features, it is important that you monitor its performance regularly to catch regressions at the earliest.

To address this problem, I am currently working on Falco, a soon-to-be-open-sourced WebPageTest test runner. Falco takes care of automating your audits, then presents the results in an easy-to-read interface while letting you read the full reports when you need it. You can follow me on Twitter to know when it goes open source, and learn more about web performance and WebPageTest!

The post Recipes for Performance Testing Single Page Applications in WebPageTest appeared first on CSS-Tricks.

CSS-Tricks

, , , , , ,
[Top]

Let Mavo Shine in Building Interactive Web Applications

As you could guess from the title, this tutorial is dedicated to Mavo: a new, approachable way to create complex, reactive, persistent web applications just by writing HTML and CSS, without a single line of JavaScript and no server backend.

The app we will build together is a flashcard study app for foreign language learners. It is a fully-fledged CRUD application that lets you:

  • Create, delete, update flashcards and re-arrange them via drag and drop.
  • Import and export flashcards.
  • Evaluate how well you’ve learned the word on a flashcard.

Here is what our finished application looks like:

In the tutorial, I will guide you through the entire process of building the app.

At the end of some steps, I provide suggestions for you to experiment with Mavo—to learn a bit more—and to make some enhancements to the application we are building.

Are you ready? Let’s get started! 😀

Static template

See the Pen
01. Static template
by Dmitry Sharabin (@dsharabin)
on CodePen.

In order to illustrate how Mavo enhances standard HTML, we will first create a purely static HTML page and then use Mavo to turn this static HTML into a fully-functional web application.

Assume we have the following HTML code inside <body>:

<header>   <h1>Flashcards</h1> </header>  <main> <article>   <p>Word or phrase</div>   <p>Translation</div> </article> </main>

In that code, the <article> element represents a single flashcard.

Let’s add some styling in order to make our HTML look more like an actual flashcards app. You can take a look at the source code and play with it here.

Getting started with Mavo

Right now, all we have is a static template. It’s time to add functionality, so it can actually work like a flashcard application. Here comes Mavo!

In order to use Mavo, we first need to include its JavaScript and CSS files in our page’s <head> section:

<head>   ...   <script src="https://get.mavo.io/mavo.min.js"></script>   <link rel="stylesheet" href="https://get.mavo.io/mavo.css">   ... </head>

Defining a Mavo app

To enable Mavo functionality on an HTML structure, we must use the mv-app attribute on the element that contains our Mavo app (which may even be the <body> or <html> element, that’s fine!). Its value is an ID for our app that should be unique in the page.

Considering that the <main> element is representing our Mavo app, let’s add the mv-app attribute to it and give our app the ID “flashcards”:

<main mv-app="flashcards">   ... </main>

The property attribute

See the Pen
02. The property attribute
by Dmitry Sharabin (@dsharabin)
on CodePen.

It’s time to tell Mavo what elements of our app are important, i.e., which elements we want to be editable and be saved.

Now we have two such elements, and they are the <p> elements. Let’s add the property attribute to those elements to tell Mavo they contain data. Elements with the property attribute are called properties.

Keep in mind that the value of the property attribute should describe the element, similarly to an id or class attribute:

...    <p property="source">Word or phrase</div>   <p property="translation">Translation</div>  ...

Notice any changes in our app? The Mavo toolbar with an Edit button appeared at the top of the page. The Edit button lets the user switch between read and edit modes. Now our app is in read mode. That means we can’t edit the data on the page.

Now lets us switch to edit mode by clicking the Edit button. What has changed? The text of the Edit button becomes Editing to indicate that we are in edit mode. If you hover over the paragraphs, Mavo communicates that you can click to edit them by highlighting them in yellow. Go ahead! Click the text and edit it. Wow! We can change the content of the page right in place!

💻 Let’s get our hands dirty!

Assume that in addition to the word and its translation, the flashcard should have an example of the word’s usage in a sentence. Enhance the app by adding the appropriate elements to the flashcard.

The mv-multiple attribute

See the Pen
03. The mv-multiple attribute
by Dmitry Sharabin (@dsharabin)
on CodePen.

At this point, we have only one flashcard in our app. That’s not very useful! For a working flashcard application, we need the ability to add, delete, and rearrange flashcards. How can we do that? We could create more flashcards by adding more <article> elements to our code, but then how does an end user create and delete flashcards?

Fortunately, Mavo has something to offer that makes this a breeze: the mv-multiple attribute, which tells Mavo that certain elements can be multiplied. It converts the element it’s used on to an editable collection of items and generates (customizable) UI for adding, deleting, and rearranging items.

Let’s use the mv-multiple attribute in our app to convert our lonely flashcard into a collection of flashcards:

<article property="flashcard" mv-multiple>   ...     </article>

Now switch the app to edit mode. Note that below the flashcard, there is now an Add flashcard button. Let’s give it a try: create a few flashcards with the help of that button. Now we can dynamically add new elements right in the app, even though there are no corresponding elements in the HTML. But that is not all!

Try hovering over a flashcard and notice the three buttons that appear near its top right corner for adding, deleting and rearranging elements via a drag and drop handle. And by hovering over any item bar button, we can understand which flashcard they correspond: Mavo highlights it. Isn’t that amazing?

The mv-storage attribute

See the Pen
04. The mv-storage attribute
by Dmitry Sharabin (@dsharabin)
on CodePen.

Now that we have the basic UI in place, let’s try the following:

  • Switch to edit mode (if you haven’t already done so).
  • Edit the first flashcard’s source word and translation. Add a couple more flashcards too.
  • Switch the app back to read mode.
  • And finally… refresh the page.

What?! Where did our data go? Wasn’t Mavo supposed to save it? What happened?

Actually, we never told Mavo if or where to store our data!

To do so, we need to use the mv-storage attribute. What options do we have? Well, Mavo opens great possibilities for us, and Mavo plugins open up even more!

In our application, we are going to store the data in the browser’s localStorage, which is one of the simplest options available, so it’s good for our first Mavo app. We just need to add the attribute mv-storage with the value local to the element with the mv-app attribute (also called the Mavo root).

<main mv-app="flashcards" mv-storage="local">   ... </main>

Have a look at the Mavo toolbar. Notice something? Another button appeared—the Save button.

Try to edit the app data one more time. Note that the Save button is now highlighted. Hover over the Save button, and Mavo will highlight the properties with the unsaved data. Isn’t that cool?

Click the Save button and refresh the page (there is no need to switch to read mode before refreshing the page). Is your data still there? Great! We are one step closer to our goal—a fully-fledged flashcard application.

The mv-autosave attribute

Now we have to click the Save button every time we need our data to be saved? That may be safer, to prevent destroying valuable data, but it can often be inconvenient. Can we just save the data automatically? Sure! To save the data automatically every time it is changed, we can use the mv-autosave attribute on our Mavo root. Its value is the number of seconds to throttle saving by. Let’s add mv-autosave="3" to the root element of our app:

<main mv-app="flashcard" mv-storage="local" mv-autosave="3">   ... </main>

Change the data one more time and have a look at the Save button. See? In the beginning, it was highlighted but after 3 seconds–it is not. All our data is now saved automatically!

So, now the main part of our app would look like that:

<main mv-app="flashcards" mv-storage="local" mv-autosave="3">   <article property="flashcard" mv-multiple>     <p property="source">Word or phrase</div>     <p property="translation">Translation</div>   </article> </main>
💻 Let’s get our hands dirty!

We are almost done with the alpha version of our app. Now it’s your turn to make the app even better. No worries, you have all the knowledge you need.

Enhance the app so as flashcards could be organized by end users in different groups related to various topics, e.g., the users could gather all the flashcards corresponding to clothing in one group, all the flashcards associated with kitchen utensils in the other one, etc.

💡 Hints!

There are many ways to achieve that goal, and it’s up to you to decide what to follow. However, I’d like you to think about some questions before proceeding:

  1. What HTML element would you use as a grouping element? It would be convenient for the users if they could see the name of the group of flashcards (topic name) and could collapse the group up to the title.
  2. What Mavo attribute(s) are you going to add to that element, if any? Will the element be a property or a collection?
  3. Will end users be able to add new topics, delete and rearrange them, change the title of a topic and move flashcards between different topics?

What if you decide not to organize flashcards in groups, but instead just label them with tags that correspond to various topics? Well, that is perfectly fine. The solution with tags is also appropriate. For the sake of practice, try to accomplish that approach too.

The mv-bar attribute

See the Pen
05. The mv-bar attribute
by Dmitry Sharabin (@dsharabin)
on CodePen.

As our app stores the data locally, by default, the users of the app won’t be able to share their cards with other users. Wouldn’t it be great if we would let them export their flashcards and import somebody else’s flashcards? Thankfully, these features are already implemented in Mavo, and we can very easily add them to our app!

The mv-bar attribute controls which buttons are going to appear in the toolbar, if any. It’s typically specified on the Mavo root (an element with the mv-app attribute). Buttons are represented by their ids (which are very logical): edit, import, export, etc.

As we only want to add a few buttons to the default set, we can use the so-called relative syntax, which allows us to add and remove buttons from the default set without having to explicitly list everything out. All we need is to start the mv-bar attribute’s value with the with keyword.

By doing that, we would get the following:

<main mv-app="flashcards"       mv-storage="local"       mv-autosave="3"       mv-bar="with import export">       ... </main>
💻 Let’s get our hands dirty!

Give those features a try: add some flashcards, try to export them in a file. Then delete existing flashcards and import the flashcards from the previously exported file.

Expressions and MavoScript

See the Pen
06. Expressions and MavoScript
by Dmitry Sharabin (@dsharabin)
on CodePen.

Let’s now add some statistics to our app, such as the number of flashcards! Sounds interesting? I hoped so. 😀

To do that, we need to learn something new about Mavo.

We can dynamically refer to the value of any property we have defined, anywhere in our Mavo app (including in HTML attributes), by putting its name inside brackets, like this: [propertyName]. This is an example of a simple expression, which allows us to dynamically calculate things, reactively as they change.

Now let’s experiment and add a [source] expression inside the flashcard property, e.g., between two properties: the source and the translation.

...   <p property="source">Word or phrase</div>   [source]   <p property="translation">Translation</div> ...

What has changed in our app? The value of the flashcard source property is now shown on the page twice.

Switch to edit mode and try to change the value of the source property. Can you see that? The page content updates while you are changing the property value! That’s why I said earlier that Mavo lets us develop reactive web applications.

That’s indeed cool, but unfortunately, in our case, it’s not really helpful: we can’t use this expression to count the number of flashcards—we would always have only one value.

What if we put the [source] expression outside the flashcard property? We will have something like that:

...   [source]   <article property="flashcard" mv-multiple>     ...   </article> ...

How does this differ from the previous case? To see the difference add some flashcards if you haven’t done so yet. Now instead of one value we have a list of comma separated values: the source property of all flashcards. That’s exactly we were looking for: the number of items in the list corresponds the number of flashcards in the app.

Makes sense? Well, yes, but it wouldn’t it be more logical if we would count the number of flashcards, not the number of values of its source property? After all, a flashcard added exists even before we fill in its source or translation. I suggest you do the following: let’s substitute the [source] expression with [flashcard]:

...   [flashcard]   <article property="flashcard" mv-multiple>     ...   </article> ...

Noticed the difference? We still have a list, but its values are not simple values but objects, i.e., complex values containing all data that pertains to each flashcard. The good news is that the number of these objects is equal to the number of flashcards, since there is one for each flashcard, even when it’s completely empty. So, right now we have an object for each flashcard, but how do we count them and display the total count?

Now let’s get familiar with the MavoScript functions and find the one that would let us count the number of flashcards. Remember, we have a list of flashcards, so we need to find a function that would let us count the number of items in a list. And here it is—the count() function does exactly that!

But how can we use functions in expressions? Are there any rules we need to be aware of? Well, yes, there is a couple:

  1. Expressions are denoted by brackets.
  2. Do not nest brackets.

Let’s try using the count() function to count the number of flashcards:

... [count(flashcard)] <article property="flashcard" mv-multiple>   ... </article> ...

And that’s exactly what we were aiming for—now we have some statistics in our app! Isn’t that cool?

💻 Let’s get our hands dirty!

I hope you’ve already warmed up and ready to continue experimenting with Mavo.

Improve the application so that the statistics are displayed not only for the total number of flashcards in the app but also for the number of flashcards in each topic separately if there are any topics.

💡Hint!
Want to filter a list based on some criteria? The where operator will help.

The self-evaluation feature

We already have an application that lets us create, edit and store multiple flashcards. But how do we keep track of which ones we have already learned and which ones we need to practice more? Any respectable flashcards application needs a self-evaluation feature. Let’s investigate how we can add that!

Suppose in our app we have two buttons for the self-evaluation: the Bad and the Good. What exactly do we want to happen every time an end user clicks the buttons? Well, the idea is rather simple:

  • Clicking the Bad button would indicate the user hasn’t learned the word yet and we want our app to move the corresponding flashcard to the beginning of the list so they could see it as soon as possible after launching the app.
  • Clicking the Good button would indicate the user has learned the word and the corresponding flashcard needs to move to the end of the list to let them work with other flashcards which they haven’t learned yet.

“Are you sure we can do that without JavaScript?” you may ask. Yep! Mavo is extremely powerful and is able to equip us with all the tools we need!

Now when we know what we are going to implement, let’s set the UI in place first and then move on to the next step. Our markup would look something like this:

... <article property="flashcard" mv-multiple>   ...   <section>     <h2>Evaluate Yourself</h2>     <button>Bad</button>     <button>Good</button>   </section> </article> ...

The mv-action attribute

See the Pen
07. The mv-action attribute
by Dmitry Sharabin (@dsharabin)
on CodePen.

Mavo actions allow us to create our very own controls that modify data in custom ways when the user interacts with them. Sounds promising right?

To define a custom action we need to use the mv-action attribute on an appropriate element inside our Mavo app. The action is performed every time the element is clicked. That’s exactly what we were looking for.

The value of the mv-action attribute is an expression. We can use any of the expression functions and syntax that MavoScript provides to us, as well as a few more to facilitate data manipulation, such as add(), set(), move(), or delete(). It is important to note that unlike normal expressions which are evaluated reactively, these expressions are only evaluated each time the action is triggered.

So, we need to move flashcards inside the collection, and Mavo has an appropriate function that lets us do that—the move() function. Its first argument refers to the item we are moving, and the second is its position in the collection. Bear in mind that elements of the collection are numbered starting from 0.

Let’s implement the first point of the outline we discussed earlier: while self-evaluating, an end user clicks the Bad button and the corresponding flashcard moves to the beginning of the collection, i.e., it becomes the first one. So in the code, we have:

... <article property="flashcard" mv-multiple>   ...   <button mv-action="move(flashcard, 0)">Bad</button>   ... </article> ...

Pay attention that in the mv-action attribute we refer to the flashcard property inside the property itself, since we want to deal with the current flashcard.

If we try to implement the second point of the outline, we will face a problem. Can you suggest what problem exactly will it be?

Let’s remember that if an end user clicks the Good button the corresponding flashcard moves to the end of the collection, i.e., it becomes the last one. To make a flashcard last in the collection we need to know the number of items in it.

Thankfully, a bit earlier we’ve already solved that task and implemented the corresponding feature. But could we use that solution to solve our current problem? Unfortunately, we can’t: as we already know, we can refer to the collection of flashcards by its name (and evaluate its size) only outside the flashcard property. But in our case, we need to do that inside it: the Good button for which we need to write an expression is inside the flashcard property.

What should we do then? I’m glad you ask. Mavo has the solution.

Using the meta element to hold intermediate values

See the Pen
08. The <meta> element
by Dmitry Sharabin (@dsharabin)
on CodePen.

So, on the one hand, we know that the [count(flashcards)] expression gives us the number of flashcards if it is evaluated outside the flashcard property. On the other hand, we need to use that value inside the flashcard property.

To solve that dilemma, we need to evaluate the number of flashcards outside the flashcard property and somehow hold the result to be able to use it elsewhere in the app, precisely inside the flashcard property. For cases like that, in Mavo, there are so-called computed properties.

To hold an intermediate result so we can refer to it, we need an HTML element in our code. It is recommended to use the <meta> element for that purpose, like so: <meta property="propertyName" content="[expression]">. The advantage of using this element is that it is hidden outside edit mode, both semantically and visually.

Now let’s add the flashcardCount computed property in our app. Remember, we must place it outside the flashcard property, but then we can refer to it from anywhere:

... <meta property="flashcardCount" content="[count(flashcard)]"> <article property="flashcard" mv-multiple>     ... </article> ...

Only one step left to finish the implementation of the self-evaluation feature: if an end user clicks the Good button the corresponding flashcard moves to the end of the collection, i.e., it becomes the last one. Let’s add the relevant action in the code of our app:

... <meta property="flashcardCount" content="[count(flashcard)]"> <article property="flashcard" mv-multiple>   ...   <button mv-action="move(flashcard, flashcardCount)">Good</button> </article> ...

We are done! Congratulations! 😀

💻 Let’s get our hands dirty!

There is another way to solve that task: with the help of the $ all special property. The $ all property represents a collection itself if it is placed inside the collection. So there is no need to use any computed property in this case. Try to implement that solution on your own.

There is only one more tiny thing left that we need to fix. Remember the part where we added some stats to our app? Remember the expression we built to evaluate the number of flashcards in the app: [count(flashcard)]? Instead, we can (and should) now use the computed property we defined. Make the appropriate changes in the app.

Takeaways

So what have we learned so far? Let’s recap. In order to turn any static HTML page into a Mavo app we need to:

  1. Include the Mavo JavaScript and CSS files in the page’s <head> section.
  2. Add the mv-app attribute to the Mavo root element.
  3. Tell Mavo what elements of our app are important by adding the property attribute to them.
  4. Place the mv-multiple attribute on the element that will be multiplied and converted into a collection.
  5. Tell Mavo where to store our data by adding mv-storage attribute to the Mavo root.
  6. Decide whether Mavo should save our data automatically or not. If yes, add the mv-autosave attribute to the Mavo root.

    We also know that:

  7. The Mavo toolbar is fully-customizable. The mv-bar attribute controls which buttons are going to appear there.
  8. Expressions let us present the current value of properties in other elements and perform computations. An expression value (and type) vary depending on the place the expression takes in the code. Mavo’s expression syntax is called MavoScript.
  9. Custom actions allow creating controls that modify data in custom ways. To define a custom action set the mv-action attribute on an appropriate element inside a Mavo app
  10. Properties whose values are expressions are called computed properties. To hold an intermediate result to be able to refer to it elsewhere in the app, it is recommended to use the <meta> element.

Instead of an epilogue

So we built our app. Is it already perfect? Of course not, nothing is! There are so many things that can be improved, and so many features that can be added (with the help of Mavo, we can even make our app multilingual!). Go ahead, enhance it more, don’t hesitate to try something new!

What we’ve learned so far about Mavo is just the tip of the iceberg, and there is so much more. I encourage you to give it a closer look, by reading the documentation, by examining examples (on the Mavo site, or on CodePen: made by Lea Verou and a few made by myself), and by creating new stuff! Good luck! 😉

Acknowledgments

I want to thank two great people. First of all, my huge thanks go to Lea Verou, who not only inspired me to write this tutorial (and helped me make it happen) but also inspires me all the time by the way she makes the world of web development a better place. I’ve never met such a gifted human being, and I am happy having an opportunity to make some stuff with her!

I also thank James Moore. The examples he uses in his course “Functional Programming for Beginners with JavaScript” on Udemy pushed me to make my very own version of a flashcard study app. He is a wonderful teacher!

The post Let Mavo Shine in Building Interactive Web Applications appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

The Many Ways to Include CSS in JavaScript Applications

Welcome to an incredibly controversial topic in the land of front-end development! I’m sure that a majority of you reading this have encountered your fair share of #hotdrama surrounding how CSS should be handled within a JavaScript application.

I want to preface this post with a disclaimer: There is no hard and fast rule that establishes one method of handling CSS in a React, or Vue, or Angular application as superior. Every project is different, and every method has its merits! That may seem ambiguous, but what I do know is that the development community we exist in is full of people who are continuously seeking new information, and looking to push the web forward in meaningful ways.

Preconceived notions about this topic aside, let’s take a look at the fascinating world of CSS architecture!

Let us count the ways

Simply Googling “How to add CSS to ” yields a flurry of strongly held beliefs and opinions about how styles should be applied to a project. To try to help cut through some of the noise, let’s examine a few of the more commonly utilized methods at a high level, along with their purpose.

Option 1: A dang ol’ stylesheet

We’ll start off with what is a familiar approach: a dang ol’ stylesheet. We absolutely are able to <link> to an external stylesheet within our application and call it a day.

<link rel="stylesheet" href="styles.css">

We can write normal CSS that we’re used to and move on with our lives. Nothing wrong with that at all, but as an application gets larger, and more complex, it becomes harder and harder to maintain a single stylesheet. Parsing thousands of lines of CSS that are responsible for styling your entire application becomes a pain for any developer working on the project. The cascade is also a beautiful thing, but it also becomes tough to manage in the sense that some styles you — or other devs on the project — write will introduce regressions into other parts of the application. We’ve experienced these issues before, and things like Sass (and PostCSS more recently) have been introduced to help us handle these issues

We could continue down this path and utilize the awesome power of PostCSS to write very modular CSS partials that are strung together via @import rules. This requires a little bit of work within a webpack config to be properly set up, but something you can handle for sure!

No matter what compiler you decide to use (or not use) at the end of the day, you’ll be serving one CSS file that houses all of the styles for your application via a <link> tag in the header. Depending on the complexity of that application, this file has the potential to get pretty bloated, hard to load asynchronously, and render-blocking for the rest of your application. (Sure, render-blocking isn’t always a bad thing, but for all intents and purposes, we’ll generalize a bit here and avoid render blocking scripts and styles wherever we can.)

That’s not to say that this method doesn’t have its merits. For a small application, or an application built by a team with less of a focus on the front end, a single stylesheet may be a good call. It provides clear separation between business logic and application styles, and because it’s not generated by our application, is fully within our control to ensure exactly what we write is exactly what is output. Additionally, a single CSS file is fairly easy for the browser to cache, so that returning users don’t have to re-download the entire file on their next visit.

But let’s say that we’re looking for a bit more of a robust CSS architecture that allows us to leverage the power of tooling. Something to help us manage an application that requires a bit more of a nuanced approach. Enter CSS Modules.

Option 2: CSS Modules

One fairly large problem within a single stylesheet is the risk of regression. Writing CSS that utilizes a fairly non-specific selector could end up altering another component in a completely different area of your application. This is where an approach called “scoped styles” comes in handy.

Scoped styles allow us to programmatically generate class names specific to a component. Thus scoping those styles to that specific component, ensuring that their class names will be unique. This leads to auto-generated class names like header__2lexd. The bit at the end is a hashed selector that is unique, so even if you had another component named header, you could apply a header class to it, and our scoped styles would generate a new hashed suffix like so: header__15qy_.

CSS Modules offer ways, depending on implementation, to control the generated class name, but I’ll leave that up to the CSS Modules documentation to cover that.

Once all is said and done, we are still generating a single CSS file that is delivered to the browser via a <link> tag in the header. This comes with the same potential drawbacks (render blocking, file size bloat, etc.) and some of the benefits (caching, mostly) that we covered above. But this method, because of its purpose of scoping styles, comes with another caveat: the removal of the global scope — at least initially.

Imagine you want to employ the use of a .screen-reader-text global class that can be applied to any component within your application. If using CSS Modules, you’d have to reach for the :global pseudo selector that explicitly defines the CSS within it as something that is allowed to be globally accessed by other components in the app. As long as you import the stylesheet that includes your :global declaration block into your component’s stylesheet, you’ll have the use of that global selector. Not a huge drawback, but something that takes getting used to.

Here’s an example of the :global pseudo selector in action:

// typography.css :global {   .aligncenter {     text-align: center;   }   .alignright {     text-align: right;   }   .alignleft {     text-align: left;   } }

You may run the risk of dropping a whole bunch of global selectors for typography, forms, and just general elements that most sites have into one single :global selector. Luckily, through the magic of things like PostCSS Nested or Sass, you can import partials directly into the selector to make things a bit more clean:

// main.scss :global {   @import "typography";   @import "forms"; }

This way, you can write your partials without the :global selector, and just import them directly into your main stylesheet.

Another bit that takes some getting used to is how class names are referenced within DOM nodes. I’ll let the individual docs for Vue, React, and Angular speak for themselves there. I’ll also leave you with a little example of what those class references look like utilized within a React component:

// ./css/Button.css  .btn {   background-color: blanchedalmond;   font-size: 1.4rem;   padding: 1rem 2rem;   text-transform: uppercase;   transition: background-color ease 300ms, border-color ease 300ms;    &:hover {     background-color: #000;     color: #fff;   } }  // ./Button.js  import styles from "./css/Button.css";  const Button = () => (   <button className={styles.btn}>     Click me!   </button> );  export default Button;

The CSS Modules method, again, has some great use cases. For applications looking to take advantage of scoped styles while maintaining the performance benefits of a static, but compiled stylesheet, then CSS Modules may be the right fit for you!

It’s worth noting here as well that CSS Modules can be combined with your favorite flavor of CSS preprocessing. Sass, Less, PostCSS, etc. are all able to be integrated into the build process utilizing CSS Modules.

But let’s say your application could benefit from being included within your JavaScript. Perhaps gaining access to the various states of your components, and reacting based off of the changing state, would be beneficial as well. Let’s say you want to easily incorporate critical CSS into your application as well! Enter CSS-in-JS.

Option 3: CSS-in-JS

CSS-in-JS is a fairly broad topic. There are several packages that work to make writing CSS-in-JS as painless as possible. Frameworks like JSS, Emotion, and Styled Components are just a few of the many packages that comprise this topic.

As a broad strokes explanation for most of these frameworks, CSS-in-JS is largely operates the same way. You write CSS associated with your individual component and your build process compiles the application. When this happens, most CSS-in-JS frameworks will output the associated CSS of only the components that are rendered on the page at any given time. CSS-in-JS frameworks do this by outputting that CSS within a <style> tag in the <head> of your application. This gives you a critical CSS loading strategy out of the box! Additionally, much like CSS Modules, the styles are scoped, and the class names are hashed.

As you navigate around your application, the components that are unmounted will have their styles removed from the <head> and your incoming components that are mounted will have their styles appended in their place. This provides opportunity for performance benefits on your application. It removes an HTTP request, it is not render blocking, and it ensures that your users are only downloading what they need to view the page at any given time.

Another interesting opportunity CSS-in-JS provides is the ability to reference various component states and functions in order to render different CSS. This could be as simple as replicating a class toggle based on some state change, or be as complex as something like theming.

Because CSS-in-JS is a fairly #hotdrama topic, I realized that there are a lot of different ways that folks are trying to go about this. Now, I share the feelings of many other people who hold CSS in high regard, especially when it comes to leveraging JavaScript to write CSS. My initial reactions to this approach were fairly negative. I did not like the idea of cross-contaminating the two. But I wanted to keep an open mind. Let’s look at some of the features that we as front-end-focused developers would need in order to even consider this approach.

  • If we’re writing CSS-in-JS we have to write real CSS. Several packages offer ways to write template-literal CSS, but require you to camel-case your properties — i.e. padding-left becomes paddingLeft. That’s not something I’m personally willing to sacrifice.
  • Some CSS-in-JS solutions require you to write your styles inline on the element you’re attempting to style. The syntax for that, especially within complex components, starts to get very hectic, and again is not something I’m willing to sacrifice.
  • The use of CSS-in-JS has to provide me with powerful tools that are otherwise super difficult to accomplish with CSS Modules or a dang ol’ stylesheet.
  • We have to be able to leverage forward-thinking CSS like nesting and variables. We also have to be able to incorporate things like Autoprefixer, and other add-ons to enhance the developer experience.

It’s a lot to ask of a framework, but for those of us who have spent most of our lives studying and implementing solutions around a language that we love, we have to make sure that we’re able to continue writing that same language as best we can.

Here’s a quick peek at what a React component using Styled Components could look like:

// ./Button.js import styled from 'styled-components';  const StyledButton= styled.button`   background-color: blanchedalmond;   font-size: 1.4rem;   padding: 1rem 2rem;   text-transform: uppercase;   transition: background-color ease 300ms, border-color ease 300ms;    &:hover {     background-color: #000;     color: #fff;   } `;  const Button = () => (   <StyledButton>     Click Me!   </StyledButton> );  export default Button;

We also need to address the potential downsides of a CSS-in-JS solution — and definitely not as an attempt to spark more drama. With a method like this, it’s incredibly easy for us to fall into a trap that leads us to a bloated JavaScript file with potentially hundreds of lines of CSS — and that all comes before the developer will even see any of the component’s methods or its HTML structure. We can, however, look at this as an opportunity to very closely examine how and why we are building components the way they are. In thinking a bit more deeply about this, we can potentially use it to our advantage and write leaner code, with more reusable components.

Additionally, this method absolutely blurs the line between business logic and application styles. However, with a well-documented and well-thought architecture, other developers on the project can be eased into this idea without feeling overwhelmed.

TL;DR

There are several ways to handle the beast that is CSS architecture on any project and do so while using any framework. The fact that we, as developers, have so many choices is both super exciting, and incredibly overwhelming. However, the overarching theme that I think continues to get lost in super short social media conversations that we end up having, is that each solution has its own merits, and its own inefficiencies. It’s all about how we carefully and thoughtfully implement a system that makes our future selves, and/or other developers who may touch the code, thank us for taking the time to establish that structure.

The post The Many Ways to Include CSS in JavaScript Applications appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Corvid by Wix: Accelerated Development of Web Applications

(This is a sponsored post.)

It’s been interesting to watch Wix evolve from a website builder into a full-fledged platform for developing web applications. It’s still just as easy for anyone to spin up a website with the visual builder that’s always been there, but Wix Code was introduced a little while back as a way to give developers more hands-on control of the code under the hood to make custom sites.

Well, that evolution continues as Wix Code recently became Corvid by Wix.

Why the name change? It’s totally understandable when you see just how many new features and tools are available for developers. There are literally 28 features in all, from a payment API and custom forms to CRM functionality and a Node.js server for writing JavaScript for both the front and back end. There’s a ton of control and power and it’s certainly worth checking out.

But what we really want to spotlight here are the brand-new features the Wix team rolled out along with the name change earlier this month.

Connect to External Data Sources

Wix has provided a built-in database for a while, but now Corvid works with external data. That means you get even more control over the data on a Wix site and moer opportunities to fetch and optimize data. We’ve talked about the numerous ways to use spreadsheets as data sources before. Now, that same concept can be brought into the Wix ecosystem!

Testing and Deploying Changes

Want to see if changing the color of a button from green to purple increases conversion? Or maybe you’re trying to decide between two new page layouts and aren’t sure which one will work best? Corvid lets you have it both ways with a feature to create a release candidate and serve it to a percentage of visitors before rolling it out to everyone. It’s native A/B testing, which is a powerful marketing technique, not to mention a solid way to test user experience.

Local Development

The front-end visual editor in Wix makes building and editing sites an easy experience. It’s especially great for those who don’t work with code often or even at all.

But many CSS-Tricks readers like yourself enjoy working with code and are good at it. Corvid brings a built-in IDE to the table. Or, if you prefer, pull your Wix project files into your local environment and use the code editor of your choice.

So, whether you’re more comfortable working with a visual interface, a built-in editor, or locally, Corvid has got you covered.

App Monitoring

Need access to console logs, HTTP functions, and web module functions? Yep, Corvid offers all of that, too. The system continually monitors Wix sites and logs activity all the while so you know when an error takes place and what caused it. Those of you who have worked with monitoring services before know how great it is to have error logs for quickly finding and fixing the source of an issue — and now it’s built right into Wix.

Speaking of working with monitoring services, Corvid will integrate with those as well so you never have to interrupt things or make a switch if you don’t want to. So nice!

Start Playing with Corvid!

What we’ve covered here is merely the tip of the iceberg when it comes to Corvid and all that it offers for a complete development platform and framework. Plus, there’s so much more to come, so definitely keep an eye out for new updates and releases as they’re announced… which we’ve seen moves at a fast pace.

Meet Corvid

Direct Link to ArticlePermalink

The post Corvid by Wix: Accelerated Development of Web Applications appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Using Parcel as a Bundler for React Applications

You may already be familiar with webpack for asset management on projects. However, there’s another cool tool out there called Parcel, which is comparable to webpack in that it helps with hassle-free asset bundling. Where Parcel really shines is that it requires zero configuration to get up and running, where other bundlers often require writing a ton code just to get started. Plus, Parcel is super fast when it runs because it utilizes multicore processing where others work off of complex and heavy transforms.

So, in a nutshell, we’re looking at a number of features and benefits:

  • Code splitting using dynamic imports
  • Assets handling for any type of file, but of course for HTML, CSS and JavaScript
  • Hot Module Replacement to update elements without a page refresh during development
  • Mistakes in the code are highlighted when they are logged, making them easy to locate and correct
  • Environment variables to easily distinguish between local and production development
  • A “Production Mode” that speeds up the build by preventing unnecessary build steps

Hopefully, you’re starting to see good reasons for using Parcel. That’s not to say it should be used 100% or all the time but rather that there are good cases where it makes a lot of sense.

In this article, we’re going to see how to set up a React project using Parcel. While we’re at it, we’ll also check out an alternative for Create React App that we can use with Parcel to develop React applications. The goal here is see that there are other ways out there to work in React, using Parcel as an example.

Setting up a new project

OK, the first thing we need is a project folder to work locally. We can make a new folder and navigate to it directly from the command line:

mkdir csstricks-react-parcel && $  _

Next, let’s get our obligatory package.json file in there. We can either make use of npm or Yarn by running one of the following:

## Using npm npm init -y  ## Using Yarn, which we'll continue with throughout the article yarn init -y

This gives us a package.json file in our project folder containing the default configurations we need to work locally. Speaking of which, the parcel package can be installed globally, but for this tutorial, we’ll install it locally as a dev dependency.

We need Babel when working in React, so let’s get that going:

yarn add parcel-bundler babel-preset-env babel-preset-react --dev

Next, we install React and ReactDOM…

yarn add react react-dom

…then create a babel.rc file and add this to it:

{   "presets": ["env", "react"] }

Next, we create our base App component in a new index.js file. Here’s a quick one that simply returns a “Hello” heading:

import React from 'react' import ReactDOM from 'react-dom' class App extends React.Component {   render() {     return (       <React.Fragment>         <h2>Hello!</h2>       </React.Fragment>     )   } }  const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);

We’ll need an HTML file where the App component will be mounted, so let’s create an index.html file inside the src directory. Again, here’s a pretty simple shell to work off of:

<html lang="en">   <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>Parcel React Example</title>   </head>   <body>     <div id="root"></div>     <script src="./index.js"></script>   </body> </html>

We will make use of the Parcel package we installed earlier. For that to work, we need to edit the start script in package.json file so it looks like this:

"scripts": {   "start": "NODE_ENV=development parcel src/index.html --open" }

Finally, let’s go back to the command line and run yarn start. The application should start and open up a fresh browser window pointing at http://localhost:1234/.

Working with styles

Parcel ships with PostCSS out of the box but, if we wanted to work with something else, we can totally do that. For example, we can install node-sass to use Sass on the project:

yarn add --dev node-sass autoprefixer

We already have autoprefixer since it’s a PostCSS plugin, so we can configure that in the postcss block of package.json:

// ... "postcss": {   "modules": false,   "plugins": {     "autoprefixer": {       "browsers": [">1%", "last 4 versions", "Firefox ESR", "not ie < 9"],       "flexbox": "no-2009"     }   } }

Setting up a production environment

We’re going to want to make sure our code and assets are compiled for production use, so let’s make sure we tell our build process where those will go. Again, in package-json:

"scripts": {   "start": "NODE_ENV=development parcel src/index.html --open",   "build": "NODE_ENV=production parcel build dist/index.html --public-url ./" }

Running the yarn run build will now build the application for production and output it in the dist folder. There are some additional options we can add to refine things a little further if we’d like:

  • --out-dir directory-name: This is for using another directory for the production files instead of the default dist directory.
  • --no-minify: Minification is enabled by default, but we can disable with this command.
  • --no-cache: This allows us to disable filesystem cache.

💩 CRAP (Create React App Parcel)

Create React App Parcel (CRAP) is a package built by Shawn Swyz Wang to help quickly set up React applications for Parcel. According to the documentation, we can bootstrap any application by running this:

npx create-react-app-parcel my-app

That will create the files and directories we need to start working. Then, we can migrate over to the application folder and start the server.

cd my-app yarn start

Parcel is all set up!

Parcel is worth exploring in your next React application. The fact that there’s no required configuration and that the bundle time is super optimized makes Parcel worth considering on a future project. And, with more than 30,000 stars on GitHub, it looks like something that’s getting some traction in the community.

Additional resources

  • Parcel Examples: Parcel examples using various tools and frameworks.
  • Awesome Parcel: A curated list of awesome Parcel resources, libraries, tools and boilerplates.

The source code for this tutorial is available on GitHub

The post Using Parcel as a Bundler for React Applications appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Writing Tests for React Applications Using Jest and Enzyme

While it is important to have a well-tested API, solid test coverage is a must for any React application. Tests increase confidence in the code and helps prevent shipping bugs to users.

That’s why we’re going to focus on testing in this post, specifically for React applications. By the end, you’ll be up and running with tests using Jest and Enzyme.

No worries if those names mean nothing to you because that’s where we’re headed right now!

Installing the test dependencies

Jest is a unit testing framework that makes testing React applications pretty darn easy because it works seamlessly with React (because, well, the Facebook team made it, though it is compatible with other JavaScript frameworks). It serves as a test runner that includes an entire library of predefined tests with the ability to mock functions as well.

Enzyme is designed to test components and it’s a great way to write assertions (or scenarios) that simulate actions that confirm the front-end UI is working correctly. In other words, it seeks out components on the front end, interacts with them, and raises a flag if any of the components aren’t working the way it’s told they should.

So, Jest and Enzyme are distinct tools, but they complement each other well.

For our purposes, we will spin up a new React project using create-react-app because it comes with Jest configured right out of the box.

yarn create react-app my-app

We still need to install enzyme and enzyme-adapter-react-16 (that number should be based on whichever version of React version you’re using).

yarn add enzyme enzyme-adapter-react-16 --dev

OK, that creates our project and gets us both Jest and Enzyme in our project in two commands. Next, we need to create a setup file for our tests. We’ll call this file setupTests.js and place it in the src folder of the project.

Here’s what should be in that file:

import { configure } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; configure({ adapter: new Adapter() });

This brings in Enzyme and sets up the adapter for running our tests.

To make things easier on us, we are going to write tests for a React application I have already built. Grab a copy of the app over on GitHub.

Taking snapshots of tests

Snapshot testing is used to keep track of changes in the app UI. If you’re wonder whether we’re dealing with literal images of the UI, the answer is no, but snapshots are super useful because they capture the code of a component at a moment in time so we can compare the component in one state versus any other possible states it might take.

The first time a test runs, a snapshot of the component code is composed and saved in a new __snapshots__ folder in the src directory. On test runs, the current UI is compared to the existing. Here’s a snapshot of a successful test of the sample project’s App component.

it("renders correctly", () => {   const wrapper = shallow(     <App />   );   expect(wrapper).toMatchSnapshot(); });

Every new snapshot that gets generated when the test suite runs will be saved in the __tests__ folder. What’s great about that Jest will check to see if the component matches is then on subsequent times when we run the test, Jest will check to see if the component matches the snapshot on subsequent tests. Here’s how that files looks.

Let’s create a conditions where the test fails. We’ll change the <h2> tag of our component from <h2>Random User</h2> to <h2>CSSTricks Tests</h2> and here’s what we get in the command line when the tests run:

If we want our change to pass the test, we either change the heading to what it was before, or we can update the snapshot file. Jest even provides instructions for how to update the snapshot right from the command line so there’s no need to update the snapshot manually:

Inspect your code changes or press `u` to update them.

So, that’s what we’ll do in this case. We press u to update the snapshot, the test passes, and we move on.

Did you catch the shallow method in our test snapshot? That’s from the Enzyme package and instructs the test to run a single component and nothing else — not even any child components that might be inside it. It’s a nice clean way to isolate code and get better information when debugging and is especially great for simple, non-interactive components.

In addition to shallow, we also have render for snapshot testing. What’s the difference, you ask? While shallow excludes child components when testing a component, render includes them while rendering to static HTML.

There is one more method in the mix to be aware of: mount. This is the most engaging type of test in the bunch because it fully renders components (like shallow and render) and their children (like render) but puts them in the DOM, which means it can fully test any component that interacts with the DOM API as well as any props that are passed to and from it. It’s a comprehensive test for interactivity. It’s also worth noting that, since it does a full mount, we’ll want to make a call to .unmount on the component after the test runs so it doesn’t conflict with other tests.

Testing Component’s Lifecycle Methods

Lifecycle methods are hooks provided by React, which get called at different stages of a component’s lifespan. These methods come in handy when handling things like API calls.
Since they are often used in React components, you can have your test suite cover them to ensure all things work as expected.

We do the fetching of data from the API when the component mounts. We can check if the lifecycle method gets called by making use of jest, which makes it possible for us to mock lifecycle methods used in React applications.

it('calls componentDidMount', () => {   jest.spyOn(App.prototype, 'componentDidMount')   const wrapper = shallow(<App />)   expect(App.prototype.componentDidMount.mock.calls.length).toBe(1) })

We attach spy to the component’s prototype, and the spy on the componentDidMount() lifecycle method of the component. Next, we assert that the lifecycle method is called once by checking for the call length.

Testing component props

How can you be sure that props from one component are being passed to another? We have a test confirm it, of course! The Enzyme API allows us to create a “mock” function so tests can simulate props being passed between components.

Let’s say we are passing user props from the main App component into a Profile component. In other words, we want the App to inform the Profile with details about user information to render a profile for that user.

First, let’s mock the user props:

const user = {   name: 'John Doe',   email: 'johndoe@gmail.com',   username: 'johndoe',   image: null }

Mock functions look a lot like other tests in that they’re wrapped around the components. However, we’re using an additional describe layer that takes the component being tested, then allows us to proceed by telling the test the expected props and values that we expect to be passed.

describe ('<Profile />', () => {   it ('contains h4', () => {     const wrapper = mount(<Profile user={user} />)     const value = wrapper.find('h4').text()     expect(value).toEqual('John Doe')   })   it ('accepts user props', () => {     const wrapper = mount(<Profile user={user} />);     expect(wrapper.props().user).toEqual(user)   }) })

This particular example contains two tests. In the first test, we pass the user props to the mounted Profile component. Then, we check to see if we can find a <h4> element that corresponds to what we have in the Profile component.

In the second test, we want to check if the props we passed to the mounted component equals the mock props we created above. Note that even though we are destructing the props in the Profile component, it does not affect the test.

Mock API calls

There’s a part in the project we’ve been using where an API call is made to fetch a list of users. And guess what? We can test that API call, too!

The slightly tricky thing about testing API calls is that we don’t actually want to hit the API. Some APIs have call limits or even costs for making making calls, so we want to avoid that. Thankfully, we can use Jest to mock axios requests. See this post for a more thorough walkthrough of using axios to make API calls.

First, we’ll create a new folder called __mock__ in the same directory where our __tests__ folder lives. This is where our mock request files will be created when the tests run.

module.exports = {   get: jest.fn(() => {     return Promise.resolve({     data: [       {         id: 1,         name: 'Jane Doe',         email: 'janedoe@gmail.com',         username: 'jdoe'       }     ]     })   }) }

We want to check and see that the GET request is made. We’ll import axios for that:

import axios from 'axios';

Just below the import statements, we need Jest to replace axios with our mock, so we add this:

jest.mock('axios')

The Jest API has a spyOn() method that takes an accessType? argument that can be used to check whether we are able to “get” data from an API call. We use jest.spyOn() to call the spied method, which we implemented in our __mock__ file, and it can be used with the shallow, render and mount tests we covered earlier.

it('fetches a list of users', () => {   const getSpy = jest.spyOn(axios, 'get')   const wrapper = shallow(     <App />   )   expect(getSpy).toBeCalled() })

We passed the test!

That’s a primer into the world of testing in a React application. Hopefully you now see the value that testing adds to a project and how relatively easy it can be to implement, thanks to the heavy lifting done by the joint powers of Jest and Enzyme.

Further reading

, , , , , ,
[Top]