This repo is a Fluid starter template that was created to answer the question "how do I create a Fluid app that is more complex than Hello World?" To answer this question this repo makes the following assumptions:
In this readme we'll walk you through the following topics:
defaultData
of those DDSesmodel
to access and modify your Fluid datainitialState
queries
actions
reducer
queries
actions
To run our local server, Tinylicious, on the default values of localhost:7070
, please enter the following into a terminal window:
npx tinylicious
Now, with our local service running in the background, we need to connect the application to it. The app has already been configured to this so now we just need to run the following in a new terminal window to start the app.
npm i
npm run start
To see how this is working, take a look at config.ts
where you will see the following values specified:
export const connectionConfig: FrsConnectionConfig = useFrs
? {
tenantId: 'YOUR-TENANT-ID-HERE',
tokenProvider: new FrsAzFunctionTokenProvider('YOUR-AZURE-FUNCTION-URL-HERE', {
userId: user.id,
userName: (user as any).name,
}),
orderer: 'YOUR-ORDERER-URL-HERE',
storage: 'YOUR-STORAGE-URL-HERE',
}
: {
tenantId: 'local',
tokenProvider: new InsecureTokenProvider('fooBar', user),
orderer: 'http://localhost:7070',
storage: 'http://localhost:7070',
};
When just starting the app with npm run start
, the useFrs
value here is false and the second set of values will be used. Here, we see that our orderer and storage URLs that point to the service are directed towards 'http://localhost:7070'. The user
object being passed into the InsecureTokenProvider
will identify the current member's user ID and user name in the application.
To run the app against a deployed FRS instance, the first set of connectionConfig
values in config.ts
need to be updated as the useFrs
boolean will now be set to true. The tenant ID, orderer, and storage URLs should match those provided to you as part of the FRS onboarding process.
As we can see, the tokenProvider
value here is now an FrsAzFunctionTokenProvider
which will make a request to an Azure function to return a signed token for the provided user. This is done so that the tenant key, that is also provided during FRS onboarding, does not need to be stored on client-side code. Instead, the Azure function is responsible for fetching the appropriate key for the tenantId
we provided and signing the token using it. Please see this repo to clone an example Azure function that provides the API that this token provider would use.
Once our Azure function is set up, we just need to pass in the URL for it to the FrsAzFunctionTokenProvider
constructor.
After filling these values in, please run the following commands in a terminal window:
npm i
npm run start:frs
NOTE: It is possible to insecurely run the application against FRS without an Azure function. However, this risks exposing the tenant key in the client-side code and should only be used for testing purposes, like so:
const connectionConfig = {
tenantId: 'YOUR-TENANT-ID-HERE',
tokenProvider: new InsecureTokenProvider('YOUR-TENANT-KEY-HERE', user),
orderer: 'YOUR-ORDERER-URL-HERE',
storage: 'YOUR-STORAGE-URL-HERE',
};
Please replace this with another implementation of the ITokenProvider
, such as the FrsAzFunctionTokenProvider
that will not expose the tenant key in the client code itself.
To deploy this application and get a URL that we can share with other people in a non-local context, we will be using an Azure App Service.
NOTE: These instructions are for deploying the front-end web application that we are building in this repo, not the backend FRS instance itself. Obtaining an already deployed FRS tenant ID is a pre-requisite for this as the local Tinylicious service instance will not work for remote deployments.
We also need to set up the app to connect to FRS using the instructions identified above. The requirements for them are:
Once you have completed local development using the instructions above, we need to first prepare the JS bundle to send to the app service. For this, please run the following command from the root directory:
npm run build
This will package the application in the form where it was connected to FRS, i.e. while running npm run start:frs
before.
Now, we should see a new /build
folder in our application root directory holding the JS bundle.
To send it to our app service, we will be using the Azure App Service VS Code Extension
Once you've logged in to your Azure account on the extension, please use the following steps to create a new app service (if you already have one created, you can skip these):
Use Ctrl+Shift+P to open the command palette.
Enter "create web" then select Azure App Service: Create New Web App...Advanced.
Respond to the prompts as follows:
Once the app has been created (or if you're using an existing one), right-click on it in the list of App Services within the extension pane. Then, select the option "Deploy to Web App...".
This will bring up a prompt to "Select the folder to deploy". Browse to the ./build
folder and select it.
You should now see a notification indicating that deployment is commencing and you can view the output in a terminal window.
Once it is completed, click on "Browse Website" to open up the app home page.
Now, you can start sharing links for different created containers. After clicking on "Create" from the home page, the app url will be of the format https://{YOUR-APPSERVICE-NAME}.azurewebsites.net/fluid/{CONTAINER-ID}
. Any users who have the page open with the same container ID should now be able to collaborate with one another!
Inside of src/config.ts
, in the containerConfig
you can modify the initialObjects
that are returned by the container.
To add another DSS to this list, make sure that the DDS is imported from @fluid-experimental/fluid-framework
, select a key, and add the DDS to initialObjects
.
import { SharedMap, ShareString } from '@fluid-experimental/fluid-framework';
export const containerConfig = {
name: 'cra-demo-container',
initialObjects: {
myMap: SharedMap,
myStringName: SharedString
},
};
Once added, you can assign default data and then access then in the model
, both of which are described below.
defaultData
of those DDSesInside of src/config.ts
you can modify the setDefaultData
function to change the data added to the initial DDSes upon container creation. Any initialObjects
specified above will be available on fluidContainer.initialObjects
.
export const setDefaultData = (fluidContainer: FluidContainer) => {
const { myMap, myStringName } = fluidContainer.intitialObjects;
...
}
model
to access and modify your Fluid dataThis project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.