Vue.js & SharePoint (scratching a niche)
Hope you find this informative (I’m probably gonna catch a lot of sh|t for this, but hold your flaying until the end?).
[trigger warning] If you are a Vue purist, be warned, this is not for you or the faint of heart.
This is really ONLY intended for those who have a corporate SharePoint system that can be utilized, NOT to be considered by those who are building applications with “dedicated” backend web and database services.
This is not a short article. I have put as much into it as I could think of off the top of my head, based on what I’m currently actually doing (and I am using this in production). I may ramble a bit, but I tried to put things into some sort of order. 🙂
Some history about my experiences… (skip this if you don’t need to sleep)
I had been successfully working with Microsoft LightSwitch (MS LS) a few years back and since Microsoft pulled the plug on that product line (evidently because of a patent troll), I was at a loss for something even remotely similar (which has proven to be unobtainium).
I current am using the CDN method of Vue (which i know will probably cause 99% of you reading this to swipe left), NOT the NPM build method. There are a few reasons I am using it in this way, which I will elaborate on in this article.
Microsoft SharePoint (MS SP) (2007-SP Online):
Microsoft SharePoint began adding a SOAP api in v2007 (maybe earlier) and a REST API in v2010. The REST API follows the Microsoft initiated Odata spec which gives the user some neat features with respect to REST queries (select, filter, orderby, etc.). (I could have those versions later than actually implemented). There are minor changes to the REST API but nothing too significant.
This gives MS SP the capability to be a “back end” to any modern “front end” method of SPAs.
Now, naturally, Microsoft would like you to continue to use their “front end” method or programming (.Net *.aspx, etc.) so that they have sway over your development methodologies. That’s all well and good, but does not really embrace current development trends like SPAs and JS frameworks.
Why not use Nodejs?
Now I know you’re probably saying “Why not just use Nodejs server-side and be done?”. Well, that’s a good question and I’ll address it here. Many organizations have an existing implementation of SharePoint, but may not have any implementation of Nodejs (currently). Nodejs typically replaces legacy web servers (like IIS natively or Apache, etc.) or similar functionality but you still need a database to capture most data sets for most applications (and even more than that for line of business applications). If you are “stuck” using on-premise technologies (SQL Server, Oracle, etc.), then you don’t have the flexibility and freedom to pick any back end database that you can quickly spin up on a cloud service (MongoDB, etc.).
Additionally, some organizations have legacy systems that they prefer to continue to use because of money spent on those systems, so “new” implementations like nodejs create a whole new support requirement that they may not currently have in place.
Leveraging existing technologies:
SO, if you have an existing corporate on-premise (or SP Online will work too) SP system, this may just change the way you do things (I know it did for me).
Your company spent $$$ on a SharePoint system (or subscription) for mainly document web folder sharing and SharePoint list sharing (similar to an Excel worksheet). That’s where SharePoint’s sweet spot is. The rest of SharePoint is mostly hyperlinks with some CSS to give it a new look every version. I know there are Access, Visio, and Excel, etc. services (btw, the latter removed from on-premise in 2016 and you have to install the online version of it), but I don’t know too many who actually “use” those technologies to their full potential (some folks hesitate to use them because they fear MS will discontinue that technology as they push customers to the “cloud”, see former part of this sentence for an example of that).
Since your company has so much $$$ invested in their SharePoint system, it really makes them happy when you can bring a web application to fruition within that framework. That is exactly what I am doing currently and my customers (who don’t care where an application is hosted) and corporate executives (who invested in SharePoint) couldn’t be happier.
There are some constraints that you should be aware of:
You will find several articles on the internet about how SharePoint is NOT a database. This is definitely true technically in the sense that SharePoint does not have (inherently) many functions of a database server backend which can provide services such as replication, duplication, backup, etc. BUT as a front end web developer, I want PERFORMANCE and don’t care about how the backend works as long as my REST end points work fast because it’s all about the UX.
That being said and acknowledged, SharePoint has the exact same standard structure (web client aka browser talking to a REST API for data consumption/storage) and most Microsoft Office products use it as well (Excel, Access, InfoPath, Visio, Project etc.). So I asked myself “If Microsoft uses it for a viable REST data source, why can’t I?”. The truth is that it works GREAT as a REST API backend to my Vuejs front end applications.
Ahhh, but the constraints…
SharePoint lists (everything is a list in SharePoint under the covers) have a 30,000,000 item limit which is pretty large, BUT SP Out-Of-The-Box (OOTB) will (by default) only display around 4500 “records” before it poops out (something about performance, blah, blah, blah!). So if you want to store 30,000,000 records and display them all at the same time, this methodology is not for you. BUT I have found that MANY line-of-business applications (especially workgroup/department level applications with 10s-100s of users)
[I guarantee that you can find at least one process that YOUR department implements that uses email (and possibly Excel) as the workflow/repository which takes significant unnecessary labor hours to aggregate or report against.]
do not require that level of record retention. In addition, you can shard the data in any way you would like across multiple SharePoint lists (by month, by year, by last name, etc.) which allows you to have flexibility in your backend structure.
This is the only constraint that I have found that is significant in the development of web applications hosted in SharePoint. I have not run into anything else that I could not do in the SharePoint environment (that means there may be more, but I haven’t found them yet).
Fragility (access control, access control, and access control):
With any application, it is as fragile as the people managing it permit. If a DBA is not locking down the database or the web server administrator is not doing their due diligence in ensuring that everything is configured properly, the application is at risk of failure or data loss, data leakage, etc. With a separation of duties, web administrators don’t typically have access to databases and DBAs don’t have access to web server configurations (I think you get the idea).
Within SharePoint, permissions are similar to Microsoft NTFS permissions (cumulative permissions, either inherited or direct, at the resource) and therefore access control is paramount in keeping the right people in and the wrong people out of certain areas. For example, you would not want users being able to write/delete from the code document library, so care should be taken to ensure that the proper access is granted. You would not want general users changing configuration for the entire application, so care should be taken there as well. I hope you’re getting the picture that access control is the key to keeping your application stable and available.
One saving grace of SharePoint is that it has a 30 day (30 by default) recycle bin for each site which can immediately restore a deleted item(s), returning inadvertent deletion of data or code back to production. I don’t know for sure, but I don’t think SQL or Oracle does that.
What SharePoint provides OOTB:
MS SP provides authentication (usually integrated with Active Directory, which provides non-repudiation for those that need it, I use it for “signing” workflows without the need to digitally sign a PDF document because of the security link between the user’s AD account and their SP account, if your organization uses smart cards, then the user’s digital certificate is typically also associated with their AD account), authorization (SharePoint groups and site access control), web hosting (SharePoint document libraries are perfect for name spacing and all relative paths are to the root of the doc lib), and fully relational data sources (SP Lists and Document Libraries) with full ODATA REST API end points per site. SharePoint lists can reference another list (think of the lists as SQL tables) which provides a foreign key for the lookup list which is fully relational, just as a SQL table does which makes SharePoint lists capable of relational normalized data structures (I know, I know, it’s NOT a database). Another capability that I have yet to investigate is the ability to have access control on a single item in a document library (a SP list cannot do this), which would give the ability to restrict access on an item level which typical database backends can’t even do.
So what that leaves me with (as a developer) is front end coding for my application and the business logic I need with respect to the UI.
Now some would argue that you should put your business logic on the server and if i were developing a public application that I wanted to make sure the “source” code was obfuscated, then I would agree. BUT if I’m building an application for a known set of users and their roles, then this works VERY well.
Again, I am using the CDN version of Vuejs, which makes most developers run because it’s not as “slick” or “elegant” as a NPM build and requires more understanding of a WHOLE application. Many web app developers only touch a portion of a complete application and don’t need to understand the entire application. For my purposes, I am the only developer for a specific application and have to understand the entire application. My method is somewhat unconventional but it was driven by constraints that I had to work within which pointed me to this methodology. So, as a consequence, I write the “built” code instead of the “source” (which then gets transpiled into “built” code). This is somewhat more coding, but i find that I know MUCH more about how my entire application works when i go this route.
SharePoint lists can have file attachments per item, but I typically use a document library for file uploads/downloads, it just makes the data storage cleaner. SP Lists can have varied data types: string (0-255 char), long string(0-infinite), date, number, choice: (you specify the choices), SharePoint user object: (contains metadata about the authenticated user), lookup (think foreign key), and a few others. The SharePoint REST API exposes all of these types.
SharePoint has server side JS libraries that you can load to perform server side functions (the most common for me is email). I can generate an email in code, then use SOAP/REST to POST the message to the server and it will queue and forward with a SharePoint server side worker process.
Root file Naming:
SharePoint OOTB uses default.aspx as it’s default file name if none is specified in the URL. i.e. if no file is specified, SharePoint will look for a default.aspx file to render. This is an IIS setting, but SharePoint sets it OOTB. So, by placing my HTML file (typically index.html) in the root of a document library and renaming it to default.aspx, I can reference the application with a [http://mysharepoint.mydomain.com/mydoclib/] which will automatically load the default.aspx file from SharePoint. So instead of using index.html (as you might with an NPM build), I rename the file to default.aspx. SharePoint is expecting aspx code, but it interprets the HTML perfectly without aspx code.
I load Vuejs in my default.aspx file with a <script> tag and load all of my other dependency libraries as well. I have a single Vue instance instantiated and my view model is contained within the <script> tag. I typically use Vuejs filters for display filtering as well.
Other JS libraries:
I typically use Vuetifyjs for a Material Design UI setup (again, loading from a local folder in SharePoint). I use axios for AJAX calls and momentjs for date formatting. If I need graphing capabilities, I typically use D3js and C3js, depending on the graphing needs.
Development and Deployment:
When developing code, I use VSCode to edit my default.aspx. I am old school and find (as a single developer on an application) that a single file for this type of application works best. I know a co-worker prefers to work with smaller files, that’s great for him, but my preference is to work on a single file in VSCode (here’s where I’ll get a ton of sh|t, LOL). One of the beauties of Vuejs is that it gives your code structure within the Vue instance, so you have markup (HTML) and the Vue view model.
Deployment could not be easier. I literally drag my updated default.aspx file to my SharePoint document library and refresh my browser. This is almost as fast as hot-reloading on NPM development, but it’s actually on the system that will host it, so dev/prod configurations are not an issue. I typically have a DEV document library and a PROD document library, so when I am ready to “publish” my code, it’s literally a simple upload of my updated default.aspx file to my PROD document library.
My “built” code is stored in a SharePoint library and I can literally copy it to another library and it works because the root URL is determined in code. I just have to build the “backend” data structure(s) (Schema) and voila, I have a full copy of the same application running in SharePoint at a different namespace. If I need to re-brand it or change some things, it’s a matter of updating the code in the new location to the new requirement.
Keeping the data model out of the view model (dynamic schema detection):
OK, so here’s where some of the methodology shines. I was typically adding the view model structure in my Vuejs code. I was having to replicate the schema from SharePoint in my view model, so that when I did queries, they would return the correct information. I realized that I could use REST to get the SCHEMA of the SharePoint list(s) and then use REST to query for the data. So I build a getSPListSchema() method which returns the fields (columns) of the SharePoint list which I populate the view model with (using Vue.set()). This allows for a VERY dynamic capability in the backend. I can add a field (column) in SharePoint and then refresh my browser and the view model is automatically updated to the new schema. Then I can just add it to my markup where I need it and immediately have a new field (column) in my application. I cannot tell you how much time this saves when modifying the backend structure. If a customer wants a “notes” field, I simply add it to my SharePoint list, add it to my markup and update my default.aspx file.
Leveraging SharePoint backend to control UI:
Typically, I need some sort of CRUD screen(s) (and Vuetifyjs has that OOTB), so I have to decide which fields (columns) are displayed in the list (grid) and which are displayed in a create/edit screen. I would typically have to hard-code those in my view model, so that the create/edit screen has all of the fields required, but you wouldn’t want all those fields in the grid. I figured out that the REST API call which returns the fields of the list includes the Description field, which is typically not used but I decided to leverage that field in SharePoint to control some front end behavior (see fragility above). I embed in the SharePoint list description field for a column the following settings:
show=0; this determines whether the field is displayed in a CRUD grid
order=1; this determines the order of the field in a CRUD grid
rename=My Renamed Field; this renames the field if required (instead of hard coding this in my view model)
These are obviously easily changed by someone with permissions, so see fragility above.
This can be used for pretty much anything you can think of within the constraints of the Description field.
Almost all of the CRUD applications that I have built use AJAX to retrieve/save data to SharePoint. It took a little re-thinking about how I coded to get the AJAX right. I typically need to do a REST call THEN do something else. I typically use a callback passed to the AJAX call which is executed after the AJAX results are returned by the promise. I only include this section to re-iterate that AJAX is obviously a key to making this methodology work.
How I have implemented Vuejs in SharePoint is definitely not a common pattern. Most SharePoint developers will want to embed Vuejs into a SharePoint master file or web part, etc. trying to retain the SharePoint “look and feel”. I prefer to use Vuejs in a stand-alone SPA and control the entire browser, not relying on SharePoint front end structures at all. Many SharePoint users complain of not being able to find anything in SharePoint, so I “hide” SharePoint from them and give them an interface that makes sense for what they want/need.
I hope this has given you some food for thought. This is NOT intended to be a one-size-fits-all solution (because it isn’t). There will be plenty of haters out there who will say this is an absolute abomination. But given the constraints that have been placed on my organization and the tools that I DO have, I have found this VERY successful.
By using SharePoint as your hosting platform and database (I know, it’s NOT), you have effectively become a full stack developer without the constraints of having to deal with another department just to get your application up and running.
Let the flaying begin…
…My next project is using Microsoft Project server (REST API) and a graphQL API to aggregate different data sources in a single UI.