Use Fluent UI Web Components with Webpack and Typescript
Fluent UI Web Components work great with TypeScript and Webpack, using a fairly standard setup. Let's take a look at how you can set up a TypeScript+Webpack project, starting from scratch.
Setting up the package
First, let's make a directory for our new project. From the terminal:
mkdir fluent-webpack
Next, let's move into that directory, where we'll set up our project:
cd fluent-webpack
From here, we'll initialize npm:
npm init
Follow the prompts from npm, answering each question in turn. You can always accept the defaults at first and then make changes later in the package.json file.
Next, we'll install the Fluent packages, along with supporting libraries. To do that, run this command:
npm install --save @fluentui/web-components @microsoft/fast-element lodash-es
We also need to install the Webpack build tooling:
npm install --save-dev clean-webpack-plugin ts-loader typescript webpack webpack-cli webpack-dev-server
Adding configuration and source
Now that we've got our basic package and dependencies set up, let's create some source files and get things configured. Since we're going to be writing a bit of code, now is a great time to involve a code editor in the process. If you're looking for a great editor for TypeScript and front-end in general, we highly recommend VS Code.
Open the fluent-webpack
folder in your favorite editor. You should see your package.json
along with a package-lock.json
and a node_modules
folder.
First, let's create a src
folder where we'll put all our TypeScript code. In the src
folder, add a main.ts
file. You can leave the file empty for now. We'll come back it in a bit.
Next, in the root of your project folder, add a tsconfig.json
file to configure the TypeScript compiler. Here's an example starter config that you can put into that file:
{
"compilerOptions": {
"pretty": true,
"target": "ES2015",
"module": "ES2015",
"moduleResolution": "node",
"importHelpers": true,
"experimentalDecorators": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"noEmitOnError": true,
"strict": true,
"outDir": "dist/build",
"rootDir": "src",
"lib": ["dom", "esnext"]
},
"include": ["src"]
}
You can learn more about tsconfig.json
options in the official TypeScript documentation.
Next, create a webpack.config.js
file in the root of your project folder with the following source:
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const path = require('path');
module.exports = function(env, { mode }) {
const production = mode === 'production';
return {
mode: production ? 'production' : 'development',
devtool: production ? 'source-map' : 'inline-source-map',
entry: {
app: ['./src/main.ts']
},
output: {
filename: 'bundle.js'
filename: 'bundle.js',
publicPath:'/'
},
resolve: {
extensions: ['.ts', '.js'],
modules: ['src', 'node_modules']
},
devServer: {
port: 9000,
historyApiFallback: true,
open: !process.env.CI,
devMiddleware: {
writeToDisk: true,
},
static: {
directory: path.join(__dirname, './')
}
},
plugins: [
new CleanWebpackPlugin()
],
module: {
rules: [
{
test: /\.ts$/i,
use: [
{
loader: 'ts-loader'
}
],
exclude: /node_modules/
}
]
}
}
}
This setup uses ts-loader
to process TypeScript. It will also enable both a production mode and a development mode that watches your source, recompiling and refreshing your browser as things change. You can read more about Webpack configuration in the official Webpack documentation.
To enable easy execution of both our production and development builds, let's add some script commands to our package.json
file. Find the scripts
section of your package.json
file and add the following two scripts:
"scripts": {
"build": "webpack --mode=production",
"dev": "webpack serve"
}
The build
script will build your TypeScript for production deployment while the dev
script will run the development web server so you can write code and see the results in your browser. You can run these scripts with npm run build
and npm run dev
respectively.
To complete our setup, we need to add an index.html
file to the root of our project. We'll start with some basic content as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Fluent Webpack</title>
</head>
<body>
<script src="dist/bundle.js"></script>
</body>
</html>
There's nothing special about the HTML yet other than the script
tag in the body
that references the bundle.js
file that our Webpack build will produce.
Using the components
With all the basic pieces in place, let's run our app in dev mode with npm run dev
. Webpack should build your project and open your default browser with your index.html
page. Right now, it should be blank, since we haven't added any code or interesting HTML. Let's change that.
First, open your src/main.ts
file and add the following code:
import { provideFluentDesignSystem, fastCard, fastButton } from '@fluentui/web-components';
provideFluentDesignSystem().register(fastCard(), fastButton());
This code uses the Fluent Design System to register the <fluent-card>
and <fluent-button>
components. Once you save, the dev server will rebuild and refresh your browser. However, you still won't see anything. To get some UI showing up, we need to write some HTML that uses our components. Replace the contents of the <body>
in your index.html
file with the following markup:
<body>
<fluent-card>
<h2>Hello World!</h2>
<fluent-button appearance="accent">Click Me</fluent-button>
</fluent-card>
<style>
:not(:defined) {
visibility: hidden;
}
fluent-card {
padding: 16px;
display: flex;
flex-direction: column;
}
h2 {
font-size: var(--type-ramp-plus-5-font-size);
line-height: var(--type-ramp-plus-5-line-height);
}
fluent-card > fluent-button {
align-self: flex-end;
}
</style>
<script src="dist/bundle.js"></script>
</body>
After saving your index.html
file, refresh your browser and you should see a card with text and a button.
Congratulations! You're now set up to use Fluent, TypeScript, and Webpack. You can import and use more components, build your own components, and when you are ready, build and deploy your website or app to production.