File Exists: /node_modules/.bin/node-pre-gyp Move It Away

I've danced the JavaScript framework shuffle for years starting with jQuery, then on to Angular. After being frustrated with Angular's complexity, I found React and thought I was in the clear. What seemed simple on the surface concluded upward beingness a frustrating mess. And then I institute Vue.js. It just felt correct. Information technology worked as expected. Information technology was fast. The documentation was incredible. Templating was eloquent. There was a unanimous consensus around how to handle state management, conditional rendering, two-way binding, routing, and more.

This tutorial will accept you stride by stride through scaffolding a Vue.js projection, offloading secure authentication to Okta'due south OpenID Connect API (OIDC), locking down protected routes, and performing Crud operations through a backend Residuum API server. This tutorial uses the post-obit technologies but doesn't require intimate cognition to follow along:

  • Vue.js with Vue CLI, vue-router, and the Okta Vue SDK
  • Node with Express, Okta JWT Verifier, Sequelize, and Finale

Tabular array of Contents

  • About Vue.js
  • Create Your Vue.js App
  • Install Bootstrap
  • Add together Authentication with Okta
  • Customize Your App Layout in Vue
  • Take Your Vue.js Frontend and Auth Flows for a Test Drive
  • Add a Backend REST API Server
    • Add together Sequelize
  • Add Finale
    • Verify Your JWT
    • Run the Server
  • Complete the Posts Manager Component
    • Listing Posts
    • Creating Posts
    • Updating Posts
    • Deleting Posts
  • Test Your Vue.js + Node CRUD App
  • Exercise More With Vue!

Virtually Vue.js

Vue.js is a robust simply simple JavaScript framework. It has one of the lowest barriers to entry of whatever modern framework while providing all the required features for high performance web applications.

Vue.js Homepage

This tutorial covers 2 primary builds, a frontend web app and backend REST API server. The frontend will be a unmarried page application (SPA) with a homepage, login and logout, and a posts manager.

Okta'due south OpenID Connect (OIDC) will handle our spider web app's hallmark through the use of Okta's Vue SDK. If an unauthenticated user navigates to the posts manager, the web app should endeavor to authenticate the user.

The server will run Limited with Sequelize and Finale. At a high level, with Sequelize and Finale you can apace generate dynamic Residue endpoints with only a few lines of code.

You will use JWT-based authentication when making requests from the spider web app and Okta'due south JWT Verifier in an Express middleware to validate the token. Your app volition betrayal the following endpoints which all require requests to have a valid access token.

            - GET /posts - GET /posts/:id - POST /posts - PUT /posts/:id - DELETE /posts/:id                      

Create Your Vue.js App

To get your project off the basis speedily you tin can leverage the scaffolding functionality from Vue CLI. For this tutorial, you are going to apply the progressive web app (PWA) template that includes a handful of features including webpack, hot reloading, CSS extraction, and unit testing.

If you're not familiar with the tenets of PWA, check out our ultimate guide to progressive web applications.

To install the Vue CLI run:

            npm install -g @vue/cli@4.5.12 @vue/cli-init@4.five.12                      

Adjacent, you need to initialize your projection. When you run the vue init control just take all the default values.

            vue init pwa my-vue-app  cd ./my-vue-app npm install npm run dev                      

Signal your favorite browser to http://localhost:8080 and you should see the fruits of your labor:

Welcome to Your Vue.js PWA

Extra Credit: Check out the other templates available for the Vue CLI.

Install Bootstrap

Let'due south install bootstrap-vue and so y'all tin can accept advantage of the diverse premade components (plus you can keep the focus on functionality and not on custom CSS):

            npm i bootstrap-vue@2.21.ii bootstrap@4.five.3                      

To complete the installation, change ./src/primary.js to include bootstrap-vue and import the required CSS files. Your ./src/main.js file should look like this:

                          // The Vue build version to load with the `import` command              // (runtime-but or standalone) has been set up in webpack.base.conf with an alias.              import              Vue              from              '              vue              '              import              App              from              '              ./App              '              import              router              from              '              ./router              '              import              {              BootstrapVue              }              from              '              bootstrap-vue              '              import              '              bootstrap/dist/css/bootstrap.css              '              import              '              bootstrap-vue/dist/bootstrap-vue.css              '              Vue              .              use              (              BootstrapVue              )              Vue              .              config              .              productionTip              =              false              /* eslint-disable no-new */              new              Vue              ({              el              :              '              #app              '              ,              router              ,              template              :              '              <App/>              '              ,              components              :              {              App              }              })                      

Add Hallmark with Okta

Dealing with hallmark in a web app is the bane of every developer's existence. That's where Okta comes in to secure your web applications with minimal lawmaking.

Before yous begin, you'll demand a free Okta developer account. Install the Okta CLI and run okta register to sign up for a new account. If you already accept an account, run okta login. Then, run okta apps create. Select the default app proper noun, or alter it every bit you run across fit. Choose Unmarried-Page App and press Enter.

Employ http://localhost:8080/callback for the Redirect URI and have the default Logout Redirect URI of http://localhost:8080.

What does the Okta CLI practise?

The Okta CLI will create an OIDC Single-Folio App in your Okta Org. It volition add the redirect URIs you specified and grant access to the Everyone group. It will also add together a trusted origin for http://localhost:8080. You will see output like the post-obit when information technology's finished:

              Okta awarding configuration: Issuer:    https://dev-133337.okta.com/oauth2/default Client ID: 0oab8eb55Kb9jdMIr5d6                          

NOTE: You can likewise apply the Okta Admin Console to create your app. Run into Create a Vue App for more information.

So, install the Okta Vue SDK and its peer dependency, the Okta AuthJS SDK:

            npm i @okta/okta-vue@iii.1.0 @okta/okta-auth-js@4.eight.0                      

Open ./src/router/alphabetize.js and supervene upon the unabridged file with the post-obit code.

                          import              Vue              from              '              vue              '              import              Router              from              '              vue-router              '              import              Hi              from              '              @/components/Hello              '              import              PostsManager              from              '              @/components/PostsManager              '              import              OktaVue              ,              {              LoginCallback              }              from              '              @okta/okta-vue              '              import              {              OktaAuth              }              from              '              @okta/okta-auth-js              '              const              oktaAuth              =              new              OktaAuth              ({              issuer              :              '                                                https://{yourOktaDomain}                /oauth2/default              '              ,              clientId              :              '              {clientId}              '              ,              redirectUri              :              window              .              location              .              origin              +              '              /callback              '              ,              scopes              :              [              '              openid              '              ,              '              contour              '              ,              '              e-mail              '              ]              })              Vue              .              apply              (              Router              )              Vue              .              use              (              OktaVue              ,              {              oktaAuth              })              let              router              =              new              Router              ({              mode              :              '              history              '              ,              routes              :              [              {              path              :              '              /              '              ,              name              :              '              Hello              '              ,              component              :              How-do-you-do              },              {              path              :              '              /callback              '              ,              component              :              LoginCallback              },              {              path              :              '              /posts-managing director              '              ,              name              :              '              PostsManager              '              ,              component              :              PostsManager              ,              meta              :              {              requiresAuth              :              true              }              }              ]              })              consign              default              router                      

Yous'll need to replace {yourOktaDomain} and {clientId} with the values from the app you lot simply created. This volition inject an authClient object into your Vue instance which tin can exist accessed past calling this.$auth anywhere inside your Vue instance.

The final step of Okta's hallmark menses is redirecting the user dorsum to your app with the token values in the URL. The LoginCallback component included in the SDK handles the redirect and persists the tokens on the browser.

                          {              path              :              '              /callback              '              ,              component              :              LoginCallback              }                      

You besides need to lock downwardly protected routes from being accessed by unauthenticated users. This is accomplished by implementing a navigation baby-sit. As the name suggests, navigation guards are primarily used to guard navigations either by redirecting or canceling.

The Okta Vue SDK comes with navigation guards congenital-in, so any road that has the following metadata will exist protected.

                          meta              :              {              requiresAuth              :              true              }                      

Customize Your App Layout in Vue

The web app's layout is located in a component ./src/App.vue. You lot can use the router-view component to render the matched component for the given path.

For the main menu, yous'll desire to alter the visibility of certain menu items based on the condition of the activeUser:

  • Not Authenticated: Evidence only Login
  • Authenticated: Testify only Logout

You can toggle the visibility of these menu items using the v-if directive in Vue.js that checks the existence of activeUser on the component. When the component is loaded (which calls created()) or when a route changes we want to refresh the activeUser.

Open ./src/App.vue and re-create/paste the post-obit code.

                          <template>              <div              id=              "app"              >              <b-navbar              toggleable=              "md"              blazon=              "dark"              variant=              "nighttime"              >              <b-navbar-toggle              target=              "nav_collapse"              ></b-navbar-toggle>              <b-navbar-brand              to=              "/"              >My Vue App</b-navbar-make>              <b-collapse              is-nav              id=              "nav_collapse"              >              <b-navbar-nav>              <b-nav-item              to=              "/"              >Dwelling house</b-nav-particular>              <b-nav-item              to=              "/posts-director"              >Posts Manager</b-nav-item>              <b-nav-item              href=              "#"              @              click.preclude=              "login"              five-if=              "!activeUser"              >Login</b-nav-item>              <b-nav-item              href=              "#"              @              click.preclude=              "logout"              v-else              >Logout</b-nav-item>              </b-navbar-nav>              </b-collapse>              </b-navbar>              <!-- routes will be rendered here -->              <router-view              />              </div>              </template>              <script>              export              default              {              proper name              :              '              app              '              ,              data              ()              {              render              {              activeUser              :              null              }              },              async              created              ()              {              wait              this              .              refreshActiveUser              ()              },              picket              :              {              // everytime a route is changed refresh the activeUser              '              $road              '              :              '              refreshActiveUser              '              },              methods              :              {              async              login              ()              {              this              .              $auth              .              signInWithRedirect              ()              },              async              refreshActiveUser              ()              {              if              (              this              .              authState              .              isAuthenticated              )              {              this              .              activeUser              =              wait              this              .              $auth              .              getUser              ()              }              },              async              logout              ()              {              await              this              .              $auth              .              signOut              ()              expect              this              .              refreshActiveUser              ()              this              .              $router              .              push              (              '              /              '              )              }              }              }              </script>                      

Every login must have a logout. The post-obit snippet will log out your user and and then redirect the user to the homepage. This method is chosen when a user clicks on the logout link in the nav.

                          async              logout              ()              {              await              this              .              $auth              .              signOut              ()              }                      

Components are the building blocks within Vue.js. Each of your pages will be defined in the app as a component. Since the Vue CLI webpack template utilizes vue-loader, your component source files have a convention that separates template, script, and style (run into here).

Now that you've added vue-bootstrap, change ./src/components/Hello.vue to remove the average links vue-cli generates.

                          <template>              <div              course=              "hero"              >              <div>              <h1              class=              "display-iii"              >Hello Earth</h1>              <p              class=              "lead"              >This is the homepage of your vue app</p>              </div>              </div>              </template>              <style>              .hero              {              summit              :              90vh              ;              display              :              flex              ;              align-items              :              center              ;              justify-content              :              centre              ;              text-marshal              :              center              ;              }              .hero              .atomic number 82              {              font-weight              :              200              ;              font-size              :              one.5rem              ;              }              </style>                      

At this point you lot can stub out the Post Manager page to examination your authentication menstruation. Once y'all ostend authentication works, you'll start to build out the API calls and components required to perform CRUD operations on your Posts model.

Create a new file ./src/components/PostsManager.vue and paste the post-obit lawmaking:

                          <template>              <div              class=              "container-fluid mt-4"              >              <h1              class=              "h1"              >Posts Manager</h1>              <p>Simply authenticated users should meet this page</p>              </div>              </template>                      

Take Your Vue.js Frontend and Auth Flows for a Test Drive

In your last run npm run dev (if information technology's not already running). Navigate to http://localhost:8080 and y'all should see the new homepage.

Hello World

If you click Posts Manager or Login you should be directed to Okta'southward flow. Enter your Okta developer account credentials.

Note: If you are logged in to your Okta Developer Account you will be redirected automatically dorsum to the app. You can exam this by using incognito or private browsing mode.

Okta Sign-In

If successful, you should render to the homepage logged in.

Homepage after logging in

Clicking on Posts Manager link should render the protected component.

Posts Manager

Add a Backend Balance API Server

Now that users tin securely authenticate, you can build the Residual API server to perform CRUD operations on a post model. Add the following dependencies to your projection:

            npm i limited@4.17.1 cors@2.viii.5 @okta/jwt-verifier@2.1.0              \              sequelize@6.vi.2 sqlite3@5.0.2 finale-residual@1.1.1 axios@0.21.1                      

Then, create the file ./src/server.js and paste the following code.

                          const              express              =              require              (              '              express              '              )              const              cors              =              require              (              '              cors              '              )              const              bodyParser              =              require              (              '              trunk-parser              '              )              const              Sequelize              =              require              (              '              sequelize              '              )              const              finale              =              crave              (              '              finale-rest              '              )              const              OktaJwtVerifier              =              require              (              '              @okta/jwt-verifier              '              )              const              oktaJwtVerifier              =              new              OktaJwtVerifier              ({              clientId              :              '              {clientId}              '              ,              issuer              :              '                                                https://{yourOktaDomain}                /oauth2/default              '              })              let              app              =              express              ()              app              .              utilise              (              cors              ())              app              .              employ              (              bodyParser              .              json              ())              // verify JWT token middleware              app              .              apply              ((              req              ,              res              ,              next              )              =>              {              // require every request to have an dominance header              if              (              !              req              .              headers              .              authorisation              )              {              return              side by side              (              new              Error              (              '              Authorization header is required              '              ))              }              let              parts              =              req              .              headers              .              authorization              .              trim              ().              dissever              (              '                                          '              )              permit              accessToken              =              parts              .              pop              ()              oktaJwtVerifier              .              verifyAccessToken              (              accessToken              ,              '              api://default              '              )              .              then              (              jwt              =>              {              req              .              user              =              {              uid              :              jwt              .              claims              .              uid              ,              email              :              jwt              .              claims              .              sub              }              next              ()              })              .              catch              (              next              )              // jwt did non verify!              })              // For ease of this tutorial, we are going to utilize SQLite to limit dependencies              let              database              =              new              Sequelize              ({              dialect              :              '              sqlite              '              ,              storage              :              '              ./exam.sqlite              '              })              // Define our Postal service model              // id, createdAt, and updatedAt are added by sequelize automatically              let              Post              =              database              .              define              (              '              posts              '              ,              {              title              :              Sequelize              .              Cord              ,              body              :              Sequelize              .              TEXT              })              // Initialize finale              finale              .              initialize              ({              app              :              app              ,              sequelize              :              database              })              // Create the dynamic REST resource for our Post model              allow              userResource              =              finale              .              resource              ({              model              :              Post              ,              endpoints              :              [              '              /posts              '              ,              '              /posts/:id              '              ]              })              // Resets the database and launches the express app on :8081              database              .              sync              ({              force              :              true              })              .              and so              (()              =>              {              app              .              heed              (              8081              ,              ()              =>              {              console              .              log              (              '              listening to port localhost:8081              '              )              })              })                      

Brand sure to replace the variables {yourOktaDomain} and {clientId} in the above code with values from your OIDC app in Okta.

Add together Sequelize

Sequelize is a promise-based ORM for Node.js. It supports the dialects PostgreSQL, MySQL, SQLite, and MSSQL and features solid transaction back up, relations, read replication, and more.

For ease of this tutorial, you're going to employ SQLite to limit external dependencies. The following code initializes a Sequelize example using SQLite as your driver.

                          allow              database              =              new              Sequelize              ({              dialect              :              '              sqlite              '              ,              storage              :              '              ./exam.sqlite              '              })                      

Each post has a championship and torso. (The fields createdAt, and updatedAt are added past Sequelize automatically). With Sequelize, you define models by calling define() on your case.

                          let              Post              =              database              .              define              (              '              posts              '              ,              {              championship              :              Sequelize              .              String              ,              body              :              Sequelize              .              TEXT              })                      

Add together Finale

Finale creates flexible Rest endpoints from Sequelize models within an Express app. If you ever coded Rest endpoints you know how much repetition at that place is. D.R.Y. FTW!

                          // Initialize finale              finale              .              initialize              ({              app              :              app              ,              sequelize              :              database              })              // Create the dynamic Balance resource for our Postal service model              let              userResource              =              finale              .              resource              ({              model              :              Post              ,              endpoints              :              [              '              /posts              '              ,              '              /posts/:id              '              ]              })                      

Verify Your JWT

This is the most crucial component of your REST API server. Without this middleware whatsoever user can perform Crud operations on our database. If no potency header is present, or the access token is invalid, or the audience doesn't match, the API telephone call will fail and render an mistake.

                          // verify JWT token middleware              app              .              use              ((              req              ,              res              ,              adjacent              )              =>              {              // require every request to have an say-so header              if              (              !              req              .              headers              .              dominance              )              {              return              next              (              new              Mistake              (              '              Authorization header is required              '              ))              }              let              parts              =              req              .              headers              .              authorization              .              trim              ().              split              (              '                                          '              )              let              accessToken              =              parts              .              pop              ()              oktaJwtVerifier              .              verifyAccessToken              (              accessToken              ,              '              api://default              '              )              .              then              (              jwt              =>              {              req              .              user              =              {              uid              :              jwt              .              claims              .              uid              ,              email              :              jwt              .              claims              .              sub              }              next              ()              })              .              grab              (              next              )              // jwt did not verify!              })                      

Run the Server

Open a new terminal window and run the server with the control node ./src/server. You lot should see debug information from Sequelize and the app listening on port 8081.

Complete the Posts Director Component

Now that the Residue API server is complete, you can start wiring upwards your posts manager to fetch posts, create posts, edit posts, and delete posts.

I always centralize my API integrations into a single helper module. This keeps the code in components much cleaner and provides single location in case you lot need to change anything with the API asking.

Create a file ./src/api.js and copy/paste the following lawmaking into it:

                          import              Vue              from              '              vue              '              import              axios              from              '              axios              '              const              client              =              axios              .              create              ({              baseURL              :              '              http://localhost:8081/              '              ,              json              :              true              })              export              default              {              async              execute              (              method              ,              resource              ,              data              )              {              // inject the accessToken for each request              let              accessToken              =              look              Vue              .              image              .              $auth              .              getAccessToken              ()              return              client              ({              method              ,              url              :              resources              ,              information              ,              headers              :              {              Say-so              :              `Bearer                            ${              accessToken              }              `              }              }).              and then              (              req              =>              {              return              req              .              data              })              },              getPosts              ()              {              return              this              .              execute              (              '              get              '              ,              '              /posts              '              )              },              getPost              (              id              )              {              render              this              .              execute              (              '              get              '              ,              `/posts/              ${              id              }              `              )              },              createPost              (              data              )              {              render              this              .              execute              (              '              post              '              ,              '              /posts              '              ,              data              )              },              updatePost              (              id              ,              data              )              {              return              this              .              execute              (              '              put              '              ,              `/posts/              ${              id              }              `              ,              information              )              },              deletePost              (              id              )              {              return              this              .              execute              (              '              delete              '              ,              `/posts/              ${              id              }              `              )              }              }                      

When yous cosign with OIDC, an access token is persisted locally in the browser. Since each API asking must have an access token, you tin fetch it from the authentication customer and set up information technology in the asking.

                          let              accessToken              =              look              Vue              .              prototype              .              $auth              .              getAccessToken              ()              return              customer              ({              method              ,              url              :              resource              ,              data              ,              headers              :              {              Authorization              :              `Bearer                            ${              accessToken              }              `              }              })                      

By creating the following proxy methods within your API helper, the code outside the helper module remains make clean and semantic.

                          getPosts              ()              {              render              this              .              execute              (              '              get              '              ,              '              /posts              '              )              },              getPost              (              id              )              {              return              this              .              execute              (              '              become              '              ,              `/posts/              ${              id              }              `              )              },              createPost              (              data              )              {              render              this              .              execute              (              '              post              '              ,              '              /posts              '              ,              data              )              },              updatePost              (              id              ,              information              )              {              return              this              .              execute              (              '              put              '              ,              `/posts/              ${              id              }              `              ,              data              )              },              deletePost              (              id              )              {              return              this              .              execute              (              '              delete              '              ,              `/posts/              ${              id              }              `              )              }                      

You lot now have all the components required to wire upward your posts manager component to brand Grime operations via the Residuum API. Open up ./src/components/PostsManager.vue and copy/paste the following lawmaking.

                          <template>              <div              grade=              "container-fluid mt-four"              >              <h1              class=              "h1"              >Posts Director</h1>              <b-warning              :prove=              "loading"              variant=              "info"              >Loading...</b-alert>              <b-row>              <b-col>              <table              grade=              "table table-striped"              >              <thead>              <tr>              <th>ID</th>              <th>Title</thursday>              <th>Updated At</thursday>              <thursday>              &nbsp;              </th>              </tr>              </thead>              <tbody>              <tr              v-for=              "post in posts"              :key=              "post.id"              >              <td>{{ post.id }}</td>              <td>{{ mail.title }}</td>              <td>{{ mail.updatedAt }}</td>              <td              class=              "text-correct"              >              <a              href=              "#"              @              click.forbid=              "populatePostToEdit(post)"              >Edit</a>              -              <a              href=              "#"              @              click.prevent=              "deletePost(post.id)"              >Delete</a>              </td>              </tr>              </tbody>              </table>              </b-col>              <b-col              lg=              "three"              >              <b-card              :title=              "(model.id ? 'Edit Post ID#' + model.id : 'New Post')"              >              <grade              @              submit.foreclose=              "savePost"              >              <b-form-grouping              label=              "Championship"              >              <b-form-input              type=              "text"              five-model=              "model.title"              ></b-form-input>              </b-form-group>              <b-form-group              label=              "Torso"              >              <b-form-textarea              rows=              "iv"              v-model=              "model.body"              ></b-form-textarea>              </b-grade-group>              <div>              <b-btn              blazon=              "submit"              variant=              "success"              >Relieve Mail service</b-btn>              </div>              </form>              </b-card>              </b-col>              </b-row>              </div>              </template>              <script>              import              api              from              '              @/api              '              export              default              {              data              ()              {              render              {              loading              :              false              ,              posts              :              [],              model              :              {}              }              },              async              created              ()              {              this              .              refreshPosts              ()              },              methods              :              {              async              refreshPosts              ()              {              this              .              loading              =              true              this              .              posts              =              await              api              .              getPosts              ()              this              .              loading              =              faux              },              async              populatePostToEdit              (              post              )              {              this              .              model              =              Object              .              assign              ({},              post              )              },              async              savePost              ()              {              if              (              this              .              model              .              id              )              {              look              api              .              updatePost              (              this              .              model              .              id              ,              this              .              model              )              }              else              {              expect              api              .              createPost              (              this              .              model              )              }              this              .              model              =              {}              // reset form              await              this              .              refreshPosts              ()              },              async              deletePost              (              id              )              {              if              (              ostend              (              '              Are you sure y'all desire to delete this post?              '              ))              {              // if we are editing a post we deleted, remove it from the form              if              (              this              .              model              .              id              ===              id              )              {              this              .              model              =              {}              }              look              api              .              deletePost              (              id              )              look              this              .              refreshPosts              ()              }              }              }              }              </script>                      

Listing Posts

Y'all'll use api.getPosts() to fetch posts from your REST API server. Yous should refresh the listing of posts when the component is loaded and later on any mutating performance (create, update, or delete).

                          async              refreshPosts              ()              {              this              .              loading              =              true              this              .              posts              =              await              api              .              getPosts              ()              this              .              loading              =              false              }                      

The attribute this.loading is toggled and so the UI tin can reflect the awaiting API call. You might not meet the loading message since the API request is not going out to the net.

Creating Posts

A course is included in the component to save a post. It's wired up to phone call savePosts() when the form is submitted and its inputs are jump to the model object on the component.

When savePost() is called, it will perform either an update or create based on the existence of model.id. This is by and large a shortcut to not take to define ii separate forms for creating and updating.

                          async              savePost              ()              {              if              (              this              .              model              .              id              )              {              await              api              .              updatePost              (              this              .              model              .              id              ,              this              .              model              )              }              else              {              expect              api              .              createPost              (              this              .              model              )              }              this              .              model              =              {}              // reset form              await              this              .              refreshPosts              ()              }                      

Updating Posts

When updating a post, you first must load the post into the form. This sets model.id which will the trigger an update in savePost().

                          async              populatePostToEdit              (              post              )              {              this              .              model              =              Object              .              assign              ({},              post              )              }                      

Important: The Object.assign() call copies the value of the post argument rather than the reference. When dealing with mutation of objects in Vue, you should always gear up to the value, not reference.

Deleting Posts

To delete a post but call api.deletePost(id). It's always good to ostend before delete so let'south throw in a native confirmation alert box to make sure the click was intentional.

                          async              deletePost              (              id              )              {              if              (              confirm              (              '              Are you lot sure you want to delete this post?              '              ))              {              await              api              .              deletePost              (              id              )              await              this              .              refreshPosts              ()              }              }                      

Test Your Vue.js + Node CRUD App

Make sure both the server and frontend are running.

Terminal #1

Terminal #two

Navigate to http://localhost:8080 and give information technology a whirl.

New Post

New Hello World Post

Delete Post

Exercise More With Vue!

Every bit I said at the top of this post, I think Vue stands head and shoulders above other frameworks. Here are five quick reasons why:

  • Uncomplicated component lifecycle
  • HTML-based templating and native ii-manner binding
  • Widely agreed upon ways to handle routing, state management, webpack configuration, and isomorphic spider web apps
  • Massive community supported resource, components, libraries, and projects
  • Vue feels very similar to React (without the JSX!) which lowers the barrier to entry for those with React feel. Moving betwixt React and Vue isn't very difficult.

I covered a lot of material in this tutorial just don't feel bad if you lot didn't grasp everything the first time. The more you work with these technologies, the more familiar they volition go.

To learn more about Vue.js head over to https://vuejs.org or check out these other great resources from the @oktadev team:

  • The Ultimate Guide to Progressive Web Applications
  • The Lazy Developer's Guide to Authentication with Vue.js
  • Build a Cryptocurrency Comparison Site with Vue.js

You can detect the source code for the application adult in this post at https://github.com/oktadeveloper/okta-vue-node-instance.

Hitting me up in the comments with any questions, and equally always, follow @oktadev on Twitter to see all the absurd content our dev team is creating.

deffellstraindich.blogspot.com

Source: https://developer.okta.com/blog/2018/02/15/build-crud-app-vuejs-node

0 Response to "File Exists: /node_modules/.bin/node-pre-gyp Move It Away"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel