Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Docker is a powerful tool that allows developers to package applications into containers—standardized executable components combining application source code with the operating system (OS) libraries and dependencies required to run that code in any environment. Dockerizing an Aurelia 2 application can simplify deployment and ensure consistency across different environments. Here's a guide on how to Dockerize an Aurelia 2 application using TypeScript and leveraging Dependency Injection (DI) concepts.
Ensure you have Docker installed on your machine. You can download it from Docker's official website.
An Aurelia 2 application created and ready to be containerized.
The Dockerfile
is a text document that contains all the commands a user could call on the command line to assemble an image. Create a Dockerfile
in the root of your Aurelia 2 project with the following content:
This multi-stage build first creates a build of the Aurelia application and then sets up a lightweight Nginx server to serve the static files.
Run the following command to build the Docker image. Replace your-app-name
with the name you wish to give your Docker image.
Once the image is built, you can run your Aurelia 2 application in a Docker container using:
This command will start a Docker container with your Aurelia 2 application running on port 8080.
By following these steps, you have successfully Dockerized your Aurelia 2 application, making it ready for easy deployment to any environment that supports Docker. Additionally, you've seen how to use Aurelia's DI system to manage services in a modern, type-safe manner using TypeScript.
In a scenario where you need to manage multiple parts of an application that might not always be active or visible at the same time, you can utilize Aurelia's ability to handle multiple root components. This can be particularly useful for scenarios like switching between a public-facing website and a private application after login, or for loading different parts of an application on demand.
Below is a step-by-step guide on how to create a multi-root Aurelia 2 application, complete with detailed explanations and code examples.
In src/main.ts
, we set up the initial root of the application. This is typically the entry point of your Aurelia app.
In src/login-wall.ts
, we define the LoginWall
class with a login
method. This method will stop the current Aurelia instance and start a new one with a different root component.
Each root component represents a different part of your application. For instance, LoginWall
could be the public-facing login page, and AppRoot
could be the main interface of the private application.
In your index.html
or equivalent, you need to have placeholders for each root component. Make sure to provide unique identifiers for each.
When switching roots, you might need to manage application state, like user sessions, and ensure a smooth transition. Consider using Aurelia's dependency injection, state management libraries, or browser storage mechanisms to maintain state across root transitions.
Routing: If your application uses routing, you'll need to configure the router for each root component separately.
Shared Resources: If multiple roots share resources like services or custom elements, ensure they are registered globally or are accessible by each root component.
Cleanup: When stopping an Aurelia app instance, make sure to clean up any event listeners or subscriptions to prevent memory leaks.
Multi-root applications in Aurelia 2 allow for a modular and dynamic approach to managing different parts of your application. By following the steps above, you can create a multi-root setup that can handle complex scenarios, such as a public and private interface transition. Remember that each application is unique, and you may need to adjust this approach to fit your specific requirements.
Learn how to achieve certain tasks in Aurelia applications. From working with third-party libraries to working with different types of data.
CSS-in-JS is a styling technique where JavaScript is used to style components. When this JavaScript is parsed, CSS is generated (usually as an <style>
element) and attached to the DOM. It allows you to abstract CSS to the component level, using JavaScript to describe styles in a declarative and maintainable way.
This method is very common in the ecosystem of some client-side libraries, such as React. So we decided to discuss how to use CSS-in-JS in Aurelia.
There are multiple implementations of CSS-in-JS concept in the form of libraries, but few of them are framework-agnostic, so we chose EmotionJS
Emotion, as described on its site, says:
Emotion is a performant and flexible CSS-in-JS library. Building on many other CSS-in-JS libraries, it allows you to style apps quickly with string or object styles. It has a predictable composition to avoid specificity issues with CSS. With source maps and labels, Emotion has a great developer experience and great performance with heavy caching in production.
To integrate EmotionJS and Aurelia, Follow the steps below: Add EmotionJS framework-agnostic version to your project with the following command
Define a custom attribute and name it Emotion, just like the following code
What is isInShadow? This method helps us to find out if our HTMLElement is inside of a shadow-root or not.
Why does shadow-root matter? Because Aurelia 2 supports ShadowDOM, we need to style those HTMLElements inside a shadow via the emotion library.
What is cache.sheet.container? The emotion library uses container configuration to inject styles into specific DOM. To support shadow-root, we should inject our styles into the shadow block but for global styles document.head
is good.
Why did we choose attached? Detecting ShadowDOM mode for an HTMLElement is possible via this life-cycle method.
Now, Register the new Emotion custom attribute in your main.ts file.
Add an object in your view model and call it cssObject.
Go to your view and add emotion custom attribute to an HTML tag.
In this recipe, we will demonstrate how to integrate Auth0 with Aurelia 2 for authentication. Auth0 provides a flexible, drop-in solution to add authentication and authorization services to your applications.
Before we begin, make sure you have:
An Auth0 account and a configured Auth0 application.
The @auth0/auth0-spa-js
package installed in your Aurelia project.
First, we'll create an authentication service that will handle the interaction with Auth0.
Replace 'YOUR_AUTH0_DOMAIN'
and 'YOUR_AUTH0_CLIENT_ID'
with the actual values from your Auth0 application settings.
Next, we'll create an Auth0 client provider to ensure our AuthService
has access to the Auth0Client instance.
Now that we have our AuthService
, we can inject it into our components to use its functionality.
After a successful login, Auth0 will redirect back to your application with the authentication result in the URL. We need to handle this in our application.
You have now integrated Auth0 with Aurelia 2 using TypeScript. This setup provides a starting point to secure your application with Auth0. Be sure to handle tokens securely and implement proper error handling as needed. Remember to replace placeholders with your actual Auth0 domain and client ID in the AuthService
.
This guide will demonstrate how to integrate Aurelia 2 with Cordova/PhoneGap for mobile application development.
Ensure you have the following installed:
Node.js and npm
Cordova CLI: npm install -g cordova
Start by creating a new Cordova project:
Add the platforms you are targeting:
Navigate to the www
directory, which Cordova uses for the web application content. You'll want to clear its contents, as we will generate the Aurelia 2 app directly in this directory.
Now, use npx makes aurelia
with the --here
flag to create a new Aurelia 2 project in the current directory without creating an additional folder:
Configure your Aurelia 2 build process to output the files directly into the www
directory. If you are using the default setup with Webpack, you may not need to change anything, as it already outputs to a dist
folder inside the current directory. However, review your configuration to ensure it aligns with Cordova's structure.
Build your Aurelia 2 application. The build process should place the output into the www
directory.
After building your Aurelia application, navigate back to the root directory of your Cordova project. You can now build the Cordova app:
Run your application on an emulator or a connected device with the following command:
You now have an Aurelia 2 application packaged within a Cordova application, ready for mobile deployment. Be sure to utilize Cordova plugins to access native device features and thoroughly test on different devices for performance and user experience.
Progressive Web Apps (PWAs) offer a near-native app experience with web technologies. They are reliable, fast, and engaging. Here's how you can build a PWA using Aurelia 2 with TypeScript and Webpack.
The service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don't need a web page or user interaction. To create a PWA, we first need to set up a service worker.
Create a new file service-worker.ts
in your src
directory:
Now, we'll register the service worker in our Aurelia app.
Create a service worker registration file service-worker-registration.ts
:
Import and call this function in your main.ts
:
Update the webpack.config.js
to include the service worker file in your build process. Make sure you install the workbox-webpack-plugin
development dependency.
Create a manifest.json
in your src
directory:
Ensure that the manifest is copied to your dist
directory during the build, and link it in your index.html
:
To test your PWA, you need to:
Run npm run build
to create the production build.
Serve your dist
directory using a static server that supports service workers (e.g., http-server
).
Open your app in a browser, and use the Chrome DevTools to audit your app with Lighthouse.
Your Aurelia 2 app should now be a fully functioning PWA! Remember to update the list of files to cache in your service worker as your app grows and changes.
Many users may be familiar with libraries such as FAST Element or lit-html . They want to know how to write strongly-typed templates with Aurelia.
In the following, we will see how to write a template as follows and introduce it to Aurelia.
To do this, we need two simple pieces of functionality so, create a strongly-typed-template
file.
The idea behind the code is really simple. First, we separate strings and variables parts inside html
function.
string(s):
variable(s):
Then, for variable parts, we remove the lambda part (VARIABLE => VARIABLE.
) by regex via parse
function. Finally, an HTML is created according to the acceptable standards for the Aurelia template engine.
The generic parameter in this function is actually your view-model.
Now, we have to introduce this strongly-typed template to Aurelia via template
option.
SignalR is a library that enables real-time web functionality in your applications. This guide will show you how to integrate SignalR with an Aurelia 2 application to create interactive, real-time features.
An existing Aurelia 2 project (you can create one using npx makes aurelia
)
.NET Core SDK installed if you're setting up a SignalR server
SignalR client library installed in your Aurelia project
If you don't have a SignalR server, create a new hub in your ASP.NET Core project:
Register the SignalR service and map the hub in Startup.cs
:
Install the SignalR client package:
or
Define an interface for the SignalR service using the DI.createInterface
function:
Inject the SignalR service into your Aurelia component and use it to send and receive messages:
And the corresponding HTML template:
You have now successfully integrated SignalR with an Aurelia 2 application, enabling real-time communication between the server and clients. This example can be expanded to include more sophisticated real-time features, such as notifications, live updates, and collaborative environments.
Remember that managing the SignalR connection's lifecycle is crucial, especially in production environments, to ensure a stable and responsive user experience.
Some users may want to inject their styles into the DOM like v1. There is no equivalent for this functionality in the second version so we can define our injectStyle
function as following:
A very simple object-to-css converter.
obj
Object-based style
No
-
Returns: a css text.
The value of cssText
will be equal to:
You can use css-to-js transformer to convert a CSS text to a JS object and use the result for toCss(result)
directly!
There is a conventional naming approach for defining your rules. Every uppercase character will change to a hyphen and a lowercase character (XyZ => -xy-z
). For example, If you want to achieve -webkit-animation
you should write WebkitAnimation
or flexDirection
will change to flex-direction
.
This is exactly what the caseConverter
function does.
A functionality to inject your text or object-based style to the html document easily!
textOrObject
Text or object-based style.
No
-
id
To set an id for your <style>
, it helps you to update an specific style tag.
Yes
-
overridable
If set this to false
, your style is only injected once but to do this you must set an id parameter too.
Yes
true
hostElement
To set your host element to inject your style into it. Useful for shadow DOM.
Yes
document.head
One of the interesting features of Aurelia 2 is the use of different file types such as Markdown as View along with HTML. To do this, follow the steps below:
Create a skeleton with Webpack
as a bundler and add markdown-loader
configuration at the end of therules
as following:
For this setting to work, you need to install the related package as well.
As a final step, we need to introduce the .md
files into the TypeScript so find the resource.d.ts
under src
folder and append the following code into it.
Now, you are able to defineMarkdown
files for your views and use them beside HTML files.
Learn how to use TailwindCSS in Aurelia 2 with this detailed guide.
Tailwind CSS is a highly customizable, low-level CSS framework that gives you all of the building blocks you need to build bespoke designs without any annoying opinionated styles you have to fight to override.
for more information take a look at Tailwind CSS
1- Run the following command in your terminal
2- Use your type of project, I am using Default Typescript with Webpack and CSS.
3- Install Tailwind CSS in your project via this command
4- After installation go to the root folder and run the below command too
This command will create a tailwind.config.js
file in the root folder beside the webpack.config.js
file with the following content
5- Open your webpack.config.js
file and add the below line into the postcssLoader
literal object as a first item in plugins
array. (Just like the picture)
6- Add these lines to the top of your main CSS file (for example my-app.css
)
In an easy way you can add the following Tailwind CSS snippet code to your project.
I have added this to my-app.html
now you can run the project by
Seems everything works
Purgecss is a tool to remove unused CSS. It can be used as part of your development workflow. Purgecss comes with a JavaScript API, a CLI, and plugins for popular build tools.
Purgecss is particularly effective with Tailwind because Tailwind generates thousands of utility classes for you, most of which you probably won't actually use. For more information, you can read Controlling File Size.
If you run the build
command, you will see the final bundle side is huge (even in production mode)
Open the tailwind.config.js
file and replace
with
Now, execute the build
command again and see the result.
GraphQL is a powerful data query language allowing you to request the data you need from your APIs. Integrating GraphQL with Aurelia 2 can be streamlined using Apollo Client, a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. In this recipe, we will set up Apollo Client within an Aurelia 2 application and demonstrate how to fetch data using GraphQL queries.
Before integrating Apollo Client, ensure you have the following installed:
Node.js and npm
An Aurelia 2 project setup
A GraphQL backend service to connect to
First, install @apollo/client
and graphql
:
Create a service to initialize Apollo Client. We will use Aurelia's dependency injection (DI) to make the client available throughout our application.
Create a new file named graphql-client.ts
in your src
directory.
Define the IGraphQLClient
interface using DI.createInterface
. This will allow us to inject the Apollo Client instance wherever we need it.
Initialize the Apollo Client with your GraphQL server's URI.
With the Apollo Client service set up, you can inject it into any Aurelia component and use it to perform GraphQL queries, mutations, or subscriptions.
In your component, import the IGraphQLClient
interface and use Aurelia's @inject
decorator to inject the Apollo Client instance.
Use the clientInstance
to send a query to your GraphQL server.
Here's an example component that fetches a list of items from a GraphQL API:
Following the steps outlined above, you successfully integrated Apollo Client into your Aurelia 2 application using the framework's dependency injection system. You can now easily perform GraphQL queries, mutations, and subscriptions throughout your application.
Remember to replace 'YOUR_GRAPHQL_API_URI'
with the actual URI of your GraphQL server. You can expand on this basic setup by adding error handling, loading states, and utilizing Apollo Client's advanced features like cache management and optimistic UI updates.
For complex applications, consider creating a separate module or feature to encapsulate all GraphQL-related logic.
Explore Apollo Client's reactive variables and local state management capabilities for a more comprehensive solution.
Use fragments in your GraphQL queries to reduce duplication and enhance maintainability.
Ensure you handle loading and error states in your components for a better user experience.
The first rule of securing client-side applications is: the client cannot be trusted. Your backend should never trust the input from the front end under any circumstance. Malicious individuals often know how to use browser debug tools and manually craft HTTP requests to your backend.
You may even find yourself in a situation where a disgruntled employee (or former employee), an engineer with intimate knowledge of the system, is seeking revenge by attempting a malicious attack.
Your primary mechanism for securing any SPA application, Aurelia or otherwise, is to work hard at securing your backend services.
Security Advice
This article only contains a few basic tips. It is in no way exhaustive, nor should it be your only resource for securing your application. The bulk of the security work you will set up in your application falls on your server-side technology. You should spend adequate time reading up on and understanding security best practices for whatever backend tech you have chosen.
When designing your application, consider which backend API calls can be made anonymously, which require a logged-in user, and which roles or permissions are required for various authenticated requests.
Ensure that your entire API surface area is explicitly covered in this way. Your front end can facilitate the login process, but ultimately this is a backend task. Here are a few related recommendations:
Make sure your server is configured to transmit sensitive resources over HTTPS. You may want to transmit all resources this way. It is more server-intensive, but it will be more secure. You must decide what is appropriate for your application.
Don't transmit passwords in plain text.
There are various ways to accomplish CORS. Prefer to use a technique based on server-supported CORS rather than client-side hacks.
Control cross-domain requests to your services. Either disallow them or configure your server using a strict allow list of allowed domains.
Require strong passwords
Never, ever store passwords in plain text.
Do not allow multiple failed login attempts to the same account.
Consider outsourcing your auth requirements to a cloud provider with greater expertise.
You can improve the user experience by plugging into Aurelia's router pipeline with your security specifics. Again, remember, this doesn't secure your app but only provides a smooth user experience. The real security is on the backend.
We have a working example here to learn how to implement authorization checks using the router.
The backend should always perform validation and sanitization of data. Do not rely on your client-side validation and sanitization code. Your client-side validation/sanitization code should not be seen as anything more than a User Experience enhancement designed to aid honest users. It will not affect anyone acting maliciously.
Here are a few things you should do, though:
Use client-side validation. This will make your users happy.
Avoid data-binding to innerHTML
. If you do, be sure to use a value converter to sanitize the input from the user.
Be extra careful anytime you are dynamically creating and compiling client-side templates based on user input.
Be extra careful anytime you are dynamically creating templates on the server based on user input, which will later be processed by Aurelia on the client.
We Are Trying To Help You
Internally, Aurelia makes no use of eval
or the Function
constructor. Additionally, all binding expressions are parsed by our strict parser, which does not make globals like window
or document
available in binding expressions. We've done this to help prevent some common abuses.
Do not embed private keys into your JavaScript code. While the average user may not be able to access them, anyone with ill intent can download your client code, un-minify it and use basic regular expressions on the codebase to find things that look like sensitive data.
Perhaps they've discovered what backend technology you are using or what cloud services your product is based on simply by studying your app's HTTP requests or looking at the page source. Using that information, they may refine their search based on certain patterns well-known to users of those technologies, making it easier to find your private keys.
If you need to acquire any secret data on the client, it should be done with great care. Here is a (non-exhaustive) list of recommendations:
Always use HTTPS to transmit this information.
Restrict which users and roles can acquire this information to an absolute minimum.
Always use time-outs on any secret keys so that, at most, if an attacker gains access, they can't use them for long.
Be careful how you store these values in memory. Do not store these as class property values or on any object linked to the DOM through data-binding or otherwise. Doing so would allow an attacker to access the information through the debug console. If you must store this information, keep it inside a private (non-exported) module-level variable.
If you need to store this information anywhere, encrypt it first.
When deploying your apps, there are a few things you can do to make it more difficult for attackers to figure out how your client works:
Bundle your application and minify it. This is the most basic obfuscation you can do.
Do not deploy the original client-side source files. Only deploy your bundled, minified app.
For additional security or IP protection, you may want to look into products such as jscrambler.
Even with the most skilled, security-proficient development team, your app will never be 100% protected. This is a fundamental assumption that you should have from the beginning. Expect to be attacked and expect someone to succeed at some point in time. What will you do if this happens? How will you respond? Will you be able to track down the culprit? Will you be able to identify the issue and quickly seal up the breach? You need a plan.
Again, most of this comes down to server-side implementation. Here are a few basic ideas:
Configure server-side logging and make sure it will provide you with useful information. Such information can be very helpful in tracking down how an attack was performed. Make sure you have tools to quickly search through your logs.
Make sure that all logins are logged. If you use an auth-token scheme, ensure all requests log this information.
Never log sensitive data.
Consider timing out logins or auth tokens. You can provide refresh mechanisms to help the user experience.
Configure server insight tooling so that threats can be detected earlier.