Nuxt is a more common solution to solve SEO. As Nuxt also has many pits, when breaking through a small technology point, there is a great sense of accomplishment, which really makes me painful and happy during this time.Here we make a summary and summary of the pits that we have traveled according to our individual learning situation.
Nuxt Development Cross Domain
Projects can use Nginx to reverse proxy external requests (note here that the Linux firewall is released on the appropriate port) to internal Nuxt on the default 3000 port. The simplest configuration file is as follows:
nuxtjs.config.js
{ modules: [ '@nuxtjs/axios', '@nuxtjs/proxy' ], proxy: [ [ '/api', { target: 'http://localhost:3001', // api host pathRewrite: { '^/api' : '/' } } ] ] }
@nuxtjs/proxy needs to be installed manually separately.
Nuxt Store uses
Using Vuex in Nuxt is not the same as using Vuex in Vue. First, Nuxt has integrated Vuex, no need for us to install it again, just refer to it directly. There is a folder of Store under the default Nuxt framework template, where we store Vuex.
Official Nuxt also provided Related Documents Can be simple, but in the official documents I see scratch.
Create two.Js files under the store file based on the official document, index.js and todo.js.And create index.vue under the pages folder.
store - index.js
export const state = () => ({ counter: 0 }) export const mutations = { increment (state) { state.counter++ } }
store - todo.js
export const state = () => ({ list: [] }) export const mutations = { add (state, text) { state.list.push({ text: text, done: false }) }, remove (state, { todo }) { state.list.splice(state.list.indexOf(todo), 1) }, toggle (state, todo) { todo.done = !todo.done } }
pages - index.vue
<template> <section class="container"> <div> <h2 @click="$store.commit('increment')">{{counter}}</h2> <ul> <li v-for="(item,index) of list" :key="index">{{item.text}}</li> </ul> </div> </section> </template> <script> import Logo from '~/components/Logo.vue' import {mapState} from "vuex"; export default { components: { Logo }, computed:{ ...mapState(["counter"]), ...mapState("todos",{ list:state => state.list }) }, created(){ for(let i =0;i<10;i++){ this.$store.commit("todos/add",i); } console.log(this.list) } } </script>
this.$store can be used directly in Nuxt and is namespace enabled by default.Take another look at the code in computed. When using mapState, the counter attribute is obtained directly, whereas the todos attribute is obtained through the namespace.What's wrong with this?
Nuxt mounts all state s, mutations, actions, getters in the index.js file in the store as their public attributes, on the store instance, whereas other files use namespaces, whose corresponding namespace name is its file name.
When running a project, you can find store.js in the.nuxt folder to see how it's done.Simply explain what the code does and what it does.
.nuxt - store.js
// Introducing vue import Vue from 'vue' // Introducing vuex import Vuex from 'vuex' // As Middleware Vue.use(Vuex) // Save console function const log = console // Properties of vuex const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations'] // store property container let store = {} // Self-executing function with no return value void (function updateModules() { // Initialize the root data, that is, the index file mentioned above as common data store = normalizeRoot(require('@/store/index.js'), 'store/index.js') // If store is a function, prompt for an exception, stop execution if (typeof store === 'function') { // Warning: Stores in Classic mode are not approved and will be deleted in Nuxt 3. return log.warn('Classic mode for store is deprecated and will be removed in Nuxt 3.') } // Execute Storage Module // store - Modular store.modules = store.modules || {} // Solve Storage Module Methods // Introduce the todos.js file, the data // 'todos.js'file name resolveStoreModules(require('@/store/todos.js'), 'todos.js') // If the environment supports hot overloading if (process.client && module.hot) { // Whenever a Vuex module is updated module.hot.accept([ '@/store/index.js', '@/store/todos.js', ], () => { // Updated root.The latest definition of the module. updateModules() // Trigger hot updates in store s. window.$nuxt.$store.hotUpdate(store) }) } })() // Create store instance // -Use store if store is function // -Otherwise, create a new instance export const createStore = store instanceof Function ? store : () => { // Return instance return new Vuex.Store(Object.assign({ strict: (process.env.NODE_ENV !== 'production') }, store)) } // Solve Storage Module Methods // moduleData - Export data // filename - File name function resolveStoreModules(moduleData, filename) { // Get export data to resolve es6 (export default) export moduleData = moduleData.default || moduleData // Remote store src +extension (. /foo/index.js -> foo/index) const namespace = filename.replace(/\.(js|mjs|ts)$/, '') // Space Name const namespaces = namespace.split('/') // Module name (state, getters, etc.) let moduleName = namespaces[namespaces.length - 1] // File Path const filePath = `store/${filename}` // If moduleName =='state' // -Execute normalizeState - Normal state // - Execute normalizeModule - Standardize Module moduleData = moduleName === 'state' ? normalizeState(moduleData, filePath) : normalizeModule(moduleData, filePath) // If executed (state, getters, etc.) if (VUEX_PROPERTIES.includes(moduleName)) { // module name const property = moduleName // Storage Module//Get Storage Module const storeModule = getStoreModule(store, namespaces, { isProperty: true }) // Merge Attributes mergeProperty(storeModule, moduleData, property) // Cancel subsequent code execution return } // Special processing index.js // Module name equals index const isIndexModule = (moduleName === 'index') // If equal to if (isIndexModule) { // Namespace pop-up last namespaces.pop() // Get module name moduleName = namespaces[namespaces.length - 1] } // Get Storage Module const storeModule = getStoreModule(store, namespaces) // Traversing VUEX_PROPERTIES for (const property of VUEX_PROPERTIES) { // Merge Attributes // storeModule - Storage Module // moduleData[property] - Stores a property data in a module // property - module name mergeProperty(storeModule, moduleData[property], property) } // If moduleData.namespaced === false if (moduleData.namespaced === false) { // Delete Namespace delete storeModule.namespaced } } // Initialize root data // moduleData - Export data // filePath - File Path function normalizeRoot(moduleData, filePath) { // Get export data to resolve es6 (export default) export moduleData = moduleData.default || moduleData // Throw an exception if commit method exists in the imported data // -You should export a method that returns a Vuex instance. if (moduleData.commit) { throw new Error(`[nuxt] ${filePath} should export a method that returns a Vuex instance.`) } // Use empty queue for merge processing if moduleData is not a function if (typeof moduleData !== 'function') { // Avoid typing errors: Set properties that only getter s have when overriding top-level keys moduleData = Object.assign({}, moduleData) } // Return after processing modularization return normalizeModule(moduleData, filePath) } // Normal state // -Modular data // -File Path function normalizeState(moduleData, filePath) { // If moduleData is not a function if (typeof moduleData !== 'function') { // Warning prompt // ${filePath} should export a method to return an object log.warn(`${filePath} should export a method that returns an object`) // Merge state const state = Object.assign({}, moduleData) // Export state as a function return () => state } // Processing modularity return normalizeModule(moduleData, filePath) } // Processing modularity // moduleData - Export data // filePath - File Path function normalizeModule(moduleData, filePath) { // If the state of the module data exists and is not a function warning prompt if (moduleData.state && typeof moduleData.state !== 'function') { // "state" should be a method to return objects in ${filePath} log.warn(`'state' should be a method that returns an object in ${filePath}`) // Merge state const state = Object.assign({}, moduleData.state) // Override the original state using function returns moduleData = Object.assign({}, moduleData, { state: () => state }) } // Return Initialization Data return moduleData } // Get the store's Model // - StorModule store data model // - namespaces namespace name array // -Whether to use the namespace default value of false function getStoreModule(storeModule, namespaces, { isProperty = false } = {}) { // If namespaces do not exist, start the namespace with a namespace name length of 1 if (!namespaces.length || (isProperty && namespaces.length === 1)) { // Return model return storeModule } // Get Namespace Name const namespace = namespaces.shift() // Save data in namespace storeModule.modules[namespace] = storeModule.modules[namespace] || {} // Enable Namespace storeModule.modules[namespace].namespaced = true // Add Named Data storeModule.modules[namespace].modules = storeModule.modules[namespace].modules || {} // recursion return getStoreModule(storeModule.modules[namespace], namespaces, { isProperty }) } // Merge Attributes // storeModule - Storage Module // moduleData - Storage module attribute data // property - module name function mergeProperty(storeModule, moduleData, property) { // If no pusher exists for moduleData if (!moduleData) return // If the module name is state if (property === 'state') { // Split state data into module space storeModule.state = moduleData || storeModule.state } else { // Other modules // Merge into corresponding module space storeModule[property] = Object.assign({}, storeModule[property], moduleData) } }
This is the compiled store file, which roughly means traversing the store file, using different solutions for different files, and mounting model s using namespaces.
Page loading
Nuxt has a Loading component available for loading. Here's the configuration.
nuxtjs.config.js
module.exports = { loading: { color: '#3B8070' } }
The loading provided by Nuxt does not meet the needs of the project. Possible projects do not need to load animations like this. so~, you need to configure one manually by yourself.Add a loading component (the official example below, see the official documentation for details) to reference it.
nuxtjs.config.js
module.exports = { loading: '~components/loading.vue' }
A small episode in Nuxt, ~and @ both point to the root directory.
components/loading.vue
<template lang="html"> <div class="loading-page" v-if="loading"> <p>Loading...</p> </div> </template> <script> export default { data: () => ({ loading: false }), methods: { start () { this.loading = true }, finish () { this.loading = false } } } </script>
Third Party Component Library
Component libraries are inevitably used in project development, which is the same as when used in Vue, and you need to add some dependencies to use them properly.
plugins - element-ui.js
import Vue from 'vue'; import Element from 'element-ui'; import locale from 'element-ui/lib/locale/lang/en'; export default () => { Vue.use(Element, { locale }) };
nuxtjs.config.js
module.exports = { css: [ 'element-ui/lib/theme-chalk/index.css' ], plugins: [ '@/plugins/element-ui', '@/plugins/router' ] };
Using Middleware
The middleware Nuxt does not give a specific usage document, but rather puts it into an editor.I feel a slight difference in this.Why do you want to do this?After a simple study, you can get a general idea.
Create the desired Middleware in middleware.Here's an example of an official website.
middleware - visits.js
export default function ({ store, route, redirect }) { store.commit('ADD_VISIT', route.path) }
This creates a middleware, but how should it be used?There are two ways to use it, one globally, the other individually on a page, where the file name is used as the name of the middleware.
++ Global Use++.
nuxtjs.config.js
export default { router: { middleware: ['visits'] } }
Use alone on a page
export default { middleware: 'auth' }
There is a code like this in the asyncData on your page on your official website.
export default { asyncData({ store, route, userAgent }) { return { userAgent } } }
Continuous updates.
summary
Nuxt has a very small learning curve, just like the Vue framework, and is already an out-of-the-box state where we can develop directly across configurations.Interested in configuration can find SSR rendering documents in the official Vue document.