The routing mode before packaging

Total code:

"use strict";
const path = require("path");
const defaultSettings = require("./src/settings.js");

function resolve(dir) {
  return path.join(__dirname, dir);
}

const name = defaultSettings.title || "vue Admin Template"; // page title

let cdn = { css: [].js: []};// Use environment variables to distinguish whether to use CDN
const isProd = process.env.NODE_ENV === "production"; // Check whether it is a production environment
let externals = {};
if (isProd) {
  // If it is a production environment, it excludes packaging otherwise it does not exclude
  externals = {
    // key(package name)/value(this value is the name of the global object in the package that needs to be fetched in the CDN)
    vue: "Vue".// The following name should be the global object name in JS
    "element-ui": "ELEMENT".// are defined globally in js
    xlsx: "XLSX" // are defined globally in js
  };
  cdn = {
    css: [
      "https://unpkg.com/element-ui/lib/theme-chalk/index.css" // Early introduction of elementUI styles].// Place the CSS file directory
    js: [
      "https://unpkg.com/vue/dist/vue.js".// vuejs
      "https://unpkg.com/element-ui/lib/index.js".// element
      "https://cdn.jsdelivr.net/npm/[email protected]/dist/xlsx.full.min.js"./ / XLSX related
      "https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js" / / XLSX related
    ] // Place the js file directory
  };
}

// If your port is set to 80,
// use administrator privileges to execute the command line.
// For example, Mac: sudo npm run
// You can change the port by the following methods:
// port = 9528 npm run dev OR npm run dev --port = 9528
const port = process.env.port || process.env.npm_config_port || 9528; // dev port

// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {
  /** * You will need to set publicPath if you plan to deploy your site under a sub path, * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/, * then publicPath should be set to "/bar/". * In most cases please use '/' !!! * Detail: https://cli.vuejs.org/config/#publicpath */
  publicPath: ". /".outputDir: "dist".assetsDir: "static".lintOnSave: process.env.NODE_ENV === "development".productionSourceMap: false.devServer: {
    port: port,
    open: true.overlay: {
      warnings: false.errors: true
    },
    proxy: {
      "/api": {
        // target: "http://ihrm-java.itheima.net",
        target: "http://192.168.68.30:66".changeOrigin: true.pathRewrite: {
          "^/api": "/api"}}}// before: require("./mock/mock-server.js")
  },
  configureWebpack: {
    // provide the app's title in webpack's name field, so that
    // it can be accessed in index.html to inject the correct title.
    name: name,
    resolve: {
      alias: {
        "@": resolve("src")}},externals: externals
  },
  chainWebpack(config) {
    // it can improve the speed of the first screen, it is recommended to turn on preload
    config.plugin("preload").tap(() = >[{rel: "preload".// to ignore runtime.js
        // https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
        fileBlacklist: [/\.map$/./hot-update\.js$/./runtime\.. *\.js$/].include: "initial"}]); config.plugin("html").tap(args= > {
      args[0].cdn = cdn;
      return args;
    });

    // when there are many pages, it will cause too many meaningless requests
    config.plugins.delete("prefetch");

    // set svg-sprite-loader
    config.module
      .rule("svg")
      .exclude.add(resolve("src/icons"))
      .end();
    config.module
      .rule("icons")
      .test(/\.svg$/)
      .include.add(resolve("src/icons"))
      .end()
      .use("svg-sprite-loader")
      .loader("svg-sprite-loader")
      .options({
        symbolId: "icon-[name]"}) .end(); config.when(process.env.NODE_ENV ! = ="development".config= > {
      config
        .plugin("ScriptExtHtmlWebpackPlugin")
        .after("html")
        .use("script-ext-html-webpack-plugin"[{// `runtime` must same as runtimeChunk name. default is `runtime`
            inline: /runtime\.. *\.js$/
          }
        ])
        .end();
      config.optimization.splitChunks({
        chunks: "all".cacheGroups: {
          libs: {
            name: "chunk-libs".test: /[\\/]node_modules[\\/]/,
            priority: 10.chunks: "initial" // only package third parties that are initially dependent
          },
          elementUI: {
            name: "chunk-elementUI".// split elementUI into a single package
            priority: 20.// the weight needs to be larger than libs and app or it will be packaged into libs or app
            test: /[\\/]node_modules[\\/]_? element-ui(.*)/ // in order to adapt to cnpm
          },
          commons: {
            name: "chunk-commons".test: resolve("src/components"), // can customize your rules
            minChunks: 3.// minimum common number
            priority: 5.reuseExistingChunk: true}}});// https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
      config.optimization.runtimeChunk("single"); }); }};Copy the code

** Target ** configures the routing mode before packaging

In SPA single-page applications, there are two routing modes

Hash mode: # follows the routing path, which is characterized by front-end access, and changes to # do not pass through the server

History mode: Normal/access mode, characterized by back-end access, any change of address will access the server

So far in development, we’ve been using hash mode, packaging and we tried to use history mode

Changing the route mode to history is easy. You only need to change the route mode type to history

const createRouter = () = > new Router({
  mode: 'history'.// require service support
  scrollBehavior: () = > ({ y: 0 }), // Manage the scrolling behavior if there is a scroll switch let the page go back to the top
  routes: [...constantRoutes] // Change to static route only
})
Copy the code

Suppose our address is www.xxxx/com/hr/a www.xxxx/com/hr/b

We will find that the domain name is actually **www.xxxx/com**, and hr is a specific prefix address. In this case, we can configure a base attribute and set it to hr

const createRouter = () = > new Router({
  mode: 'history'.// require service support
  base: '/hr/'.// Configure the base address of the project
  scrollBehavior: () = > ({ y: 0 }), // Manage the scrolling behavior if there is a scroll switch let the page go back to the top
  routes: [...constantRoutes] // Change to static route only
})
Copy the code

At this point, we will find that the address has changed to what we want

Submit code

Performance analysis and application of CDN

Objective: To analyze the performance of developed applications and the application of CDN

Performance analysis

We integrate features, we write a lot of components, we end up in a bunch of files, so how does it perform in the real world?

We can use vue-CLI’s own performance analysis tools to package and analyze all the features we developed

Its application is very simple

$ npm run preview -- --report
Copy the code

This command will do dependency analysis from our main. Js ** entry to get the largest package available for observation and optimization

After executing this command, we should see the following page

As shown in the figure, the larger the square is, the larger the file occupies, and the larger the file, the higher the requirement for network bandwidth and access speed, which is the direction of our optimization

So in this case, how do we optimize

Webpack excludes packaging

CDN is a better way

Isn’t the file big? We don’t need to package these large files and those small files together, such as XLSX, Element plug-ins with full functions, we can put them on the CDN server, on the one hand, reduce the size of the overall package, and on the other hand, the CDN acceleration service can speed up our access to the plug-in

use

Go to vue.config.js and add externals so that webPack doesn’t pack XLSX and Element

vue.config.js

 // Exclude elementUI XLSX and vue
  externals:
      {
        'vue': 'Vue'.'element-ui': 'ELEMENT'.'xlsx': 'XLSX'
     }
Copy the code

Running again, we see that the package size has been greatly reduced

CDN file configuration

But what about the modules that are not packaged?

CDN can be used in the page template in advance

vue.config.js

const cdn = {
  css: [
    // element-ui css
    'https://unpkg.com/element-ui/lib/theme-chalk/index.css' / / the style sheet].js: [
    // vue must at first!
    'https://unpkg.com/vue/dist/vue.js'.// vuejs
    // element-ui js
    'https://unpkg.com/element-ui/lib/index.js'.// elementUI
      'https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js'.'https://cdn.jsdelivr.net/npm/[email protected]/dist/xlsx.full.min.js']}Copy the code

However, please note that this configuration actually takes effect for both the development environment and the production environment. In the development environment, there is no need to use THE CDN. In this case, we can use environment variables to distinguish

let cdn = { css: [].js: []}// Use environment variables to distinguish whether to use CDN
const isProd = process.env.NODE_ENV === 'production' // Check whether it is a production environment
let externals = {}
if (isProd) {
  // If it is a production environment, it excludes packaging otherwise it does not exclude
  externals = {
    // key(package name)/value(this value is the name of the global object in the package that needs to be fetched in the CDN)
    'vue': 'Vue'.// The following name should be the global object name in JS
    'element-ui': 'ELEMENT'.// are defined globally in js
    'xlsx': 'XLSX' // are defined globally in js
  }
  cdn = {
    css: [
      'https://unpkg.com/element-ui/lib/theme-chalk/index.css' // Early introduction of elementUI styles].// Place the CSS file directory
    js: [
      'https://unpkg.com/vue/dist/vue.js'.// vuejs
      'https://unpkg.com/element-ui/lib/index.js'.// element
      'https://cdn.jsdelivr.net/npm/[email protected]/dist/xlsx.full.min.js'./ / XLSX related
      'https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js' / / XLSX related
    ] // Place the js file directory}}Copy the code

Inject the CDN file into the template

This is then injected into index.html via the html-webpack-plugin:

config.plugin('html').tap(args= > {
  args[0].cdn = cdn
  return args
})
Copy the code

Find public/index. HTML. Inject CSS and JS via your Config CDN.

<head> <! - introduction of style - > < % for (var CSS of htmlWebpackPlugin. Options. The CDN. CSS) {% > < link rel = "stylesheet" href = "< % = CSS % >" > < %} % > </head> <! - the introduction of JS - > < % for (var JS of htmlWebpackPlugin. Options. The CDN. JS) {% > < script SRC = "< % = JS % >" > < / script > < %} % >Copy the code

Finally, pack

$ npm run build:prod
Copy the code

Application and proxy across domains in nodeJS environment

The ** target ** packages the packaged code online and proxies it across domains in NodeJS

Deploy projects using the KOA framework

So far, we have completed a front-end engineer development process. As usual, at this point, o&M will deploy our code to the NGIx service of Ali Cloud. For us, we can deploy it to the native NodeJS environment

Deployment Automatic deployment or manual deployment

The first step is to create the Web services folder hrServer

$ mkdir hrServer Create hrServer folder
Copy the code

Second, in this folder, initialize NPM

$ npm init -y
Copy the code

Step 3: Install the server framework KOA (express or Egg)

$ npm i koa koa-static
Copy the code

Step 4: Copy the dist directory packaged in the previous section to **hrServer/public**

Step 5: Create app.js in the root directory

const Koa  = require('koa')
const serve = require('koa-static');

const app = new Koa();
app.use(serve(__dirname + "/public")); // Static the code under public
app.listen(3333.() = > {
     console.log('Human Resources Programme Launch')})Copy the code

At this point, we can go to http://localhost:3333

So here’s the page

Resolve the history page access problem

But there are two problems.

  1. When we refresh the page, we find 404

This is because we use the history mode, the change of address will cause the server to refresh, we just need to process all the addresses in app.js

Install koA middleware

$ npm i koa2-connect-history-api-fallback Middleware that specifically handles the History pattern
Copy the code

Registered middleware

const Koa  = require('koa')
const serve = require('koa-static');
const  { historyApiFallback } = require('koa2-connect-history-api-fallback');
const path = require('path')
const app = new Koa();
// All requests except the interface are sent to index.html
app.use(historyApiFallback({ 
     whiteList: ['/prod-api']}));// There is a whiteList
app.use(serve(__dirname + "/public")); // Static the code under public

app.listen(3333.() = > {
     console.log('Human Resources Programme Launch')})Copy the code

Solve cross-domain problems in production environment

  1. When you click login, interface 404 is found

As mentioned earlier, vue-CLI agents only exist during development, and when we go live in a Node or NGIx environment, we need to re-agent the environment

Proxy in NodeJS

Install cross-domain proxy middleware

$ npm i koa2-proxy-middleware
Copy the code

Configuring the spanning proxy

const proxy = require('koa2-proxy-middleware')

app.use(proxy({
  targets: {
    // (.*) means anything
    '/prod-api/(.*)': {
        target: 'http://ihrm-java.itheima.net/api'.// Back-end server address
        changeOrigin: true.pathRewrite: { 	
            '/prod-api': ""}}}}))Copy the code

Note: pathRewrite is used here because the production environment’s request base address is /prod-api, which needs to be removed

At this point, our project can be accessed across domains!

Up to now, we are more than ten days, completed a more complex middle anatomy and development of the project, any project is a complicated by reasonable design and layout of all sorts of function of assembled, so we each student to master the ability of the future is regardless of the difficulty and complexity of the project, all learn to decoupling and design technology, So our development capability will become stronger and stronger

That is All !

Thank you! ! !