предисловие
адрес гитхаба:GitHub.com/Ли остается Мэри…(полная ветка: оптимизация ветки)
демонстрационный адрес:vue-project-demo.eloco.cn
Установите и инициализируйте схему
Установить
узел >= 8.9 Рекомендуется: 8.11.0+
Установить:npm install -g @vue/cli
экзамен:vue --version
Если у вас установлена более старая версия, вам необходимо сначалаnpm uninstall vue-cli -g
Удалите старую версию.
Инициализировать схему
- Создайте:
vue create project-name
Примечание. Имена проектов не могут быть написаны в верблюжьем регистре.
- Выберите предустановку (здесь я выбираю дополнительные функции):
- Выберите те, которые нужно установить (Babel, Router, Vuex, Pre-processors, Linter/Formatter):
- Использовать ли режим маршрутизации истории (Да):
-
Выберите препроцессор css (Sass/SCSS):
-
Выберите конфигурацию eslint (ESLint + стандартная конфигурация):
-
Выберите, когда выполнять проверку eslint (Lint при сохранении):
-
Выберите, как настроить функции, выбранные выше (в специальных файлах конфигурации):
- Сохранять ли предыдущие настройки в качестве предустановленного шаблона (y):
Если вы выберете y, это позволит вам ввести имя для прямого использования в следующий раз, в противном случае начнется прямая инициализация проекта.
- Наконец, взгляните на сгенерированный каталог базовой схемы:
Элегантно используйте svg в своем проекте
- первый в
/src/components
СоздайтеSvgIcon.vue
:
Ссылаться на:Будущее должно быть жарким: введение в технологию SVG Sprite - Чжан Синьсюй
- существует
src/
Создать подicons
папку и создать под нейsvg
Папка используется для хранения файлов svg, созданияindex.js
В качестве входного файла:
Скрипт index.js:
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon.vue' // svg组件
// 全局注册
Vue.component('svg-icon', SvgIcon)
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)
- использовать
svg-sprite-loader
используется в проектеsvg
Обрабатывать:
npm install svg-sprite-loader --save-dev
;
изменить значение по умолчаниюwebpack
Конфигурация, созданная в корневом каталоге проектаvue.config.js
, код показан ниже;
const path = require('path')
function resolve(dir) {
return path.join(__dirname, './', dir)
}
module.exports = {
chainWebpack: config => {
// svg loader
const svgRule = config.module.rule('svg') // 找到svg-loader
svgRule.uses.clear() // 清除已有的loader, 如果不这样做会添加在此loader之后
svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
svgRule // 添加svg新的loader处理
.test(/\.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
// 修改images loader 添加svg处理
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(resolve('src/icons'))
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
}
}
- Наконец, в
main.js
введен вimport '@/icons'
Ты сможешь;
// 使用示例
<svg-icon icon-class="add" />
PS: Что касается svg, я лично рекомендую использовать библиотеку иконок с открытым исходным кодом Ali.iconFont
axios инкапсулирует API, модульный vuex
аксиомы
- Установить в проект
axios
:npm install axios
; - существует
src
Создано в каталогеutils/
и создатьrequest.js
используется для инкапсуляцииaxios
, код выше:
import axios from 'axios'
// 创建axios 实例
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
timeout: 10000 // 请求超时时间
})
// request 拦截器
service.interceptors.request.use(
config => {
// 这里可以自定义一些config 配置
return config
},
error => {
// 这里处理一些请求出错的情况
console.log(error)
Promise.reject(error)
}
)
// response 拦截器
service.interceptors.response.use(
response => {
const res = response.data
// 这里处理一些response 正常放回时的逻辑
return res
},
error => {
// 这里处理一些response 出错时的逻辑
return Promise.reject(error)
}
)
export default service
- Поскольку вы хотите использовать
axios
, необходимо настроить переменные среды и запрашиваемый адрес, который можно легко изменить здесь.poackage.json
:
"scripts": {
"dev": "vue-cli-service serve --project-mode dev",
"test": "vue-cli-service serve --project-mode test",
"pro": "vue-cli-service serve --project-mode pro",
"pre": "vue-cli-service serve --project-mode pre",
"build:dev": "vue-cli-service build --project-mode dev",
"build:test": "vue-cli-service build --project-mode test",
"build:pro": "vue-cli-service build --project-mode pro",
"build:pre": "vue-cli-service build --project-mode pre",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
Также измените vue.config.js:
const path = require('path')
function resolve(dir) {
return path.join(__dirname, './', dir)
}
module.exports = {
chainWebpack: config => {
// 这里是对环境的配置,不同环境对应不同的BASE_API,以便axios的请求地址不同
config.plugin('define').tap(args => {
const argv = process.argv
const mode = argv[argv.indexOf('--project-mode') + 1]
args[0]['process.env'].MODE = `"${mode}"`
args[0]['process.env'].BASE_API = '"http://47.94.138.75:8000"'
return args
})
// svg loader
const svgRule = config.module.rule('svg') // 找到svg-loader
svgRule.uses.clear() // 清除已有的loader, 如果不这样做会添加在此loader之后
svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
svgRule // 添加svg新的loader处理
.test(/\.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
// 修改images loader 添加svg处理
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(resolve('src/icons'))
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
}
}
- как пользоваться?
я скорее порекомендую
src/
Создать подapi
Каталог, используемый для унифицированного управления всеми запросами, например:
Преимущество этого в том, что это удобно для управления и пост-обслуживания, а также может соответствовать внутренним микросервисам и создавать несколько файлов для хранения разных модулей.api
. Остальное зависит от того, какой API вы используете, вы можете импортировать его самостоятельно.
Расширение: настройки cors на стороне сервера
Включает в себя междоменные, вот использованиеcors
,Многие знакомые часто спрашивают о принципе реализации cors в интервью.В этом интернете много теорий,которые в основном говорят так:
На самом деле это понимание очень абстрактно, как сервер проверяет?
Здесь вы можете понять это по-популярному, как бэк-энд получает фронт-эндrequest
По запросу будетrequest
перехватчик вродеaxios response
Перехватчик такой же. Ниже сphp lumen
Возьмите фреймворк в качестве примера, чтобы понять этот процесс глубже:
<?php
namespace App\Http\Middleware;
use App\Http\Utils\Code;
use Closure;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
class CorsMiddleware
{
private $headers;
/**
* 全局 : 解决跨域
* @param $request
* @param \Closure $next
* @return mixed
* @throws \HttpException
*/
public function handle($request, Closure $next)
{
//请求参数
Log::info('http request:'.json_encode(["request_all" => $request->all()]));
$allowOrigin = [
'http://47.94.138.75',
'http://localhost',
];
$Origin = $request->header("Origin");
$this->headers = [
'Access-Control-Allow-Headers' => 'Origin,x-token,Content-Type',
'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Credentials' => 'true',//允许客户端发送cookie
'Access-Control-Allow-Origin' => $Origin,
//'Access-Control-Max-Age' => 120, //该字段可选,间隔2分钟验证一次是否允许跨域。
];
//获取请求方式
if ($request->isMethod('options')) {
if (in_array($Origin, $allowOrigin)) {
return $this->setCorsHeaders(new Response(json_encode(['code' => Code::SUCCESS, "data" => 'success', "msg" => ""]), Code::SUCCESS));
} else {
return new Response(json_encode('fail', 405));
}
}
$response = $next($request);
//返回参数
Log::info('http response:'.json_encode($response));
return $this->setCorsHeaders($response);
}
/**
* @param $response
* @return mixed
*/
public function setCorsHeaders($response)
{
foreach ($this->headers as $key => $val) {
$response->header($key, $val);
}
return $response;
}
}
vuex статьи
При создании проекта выберитеvuex
, то значение по умолчанию будет вsrc
Есть каталогstore.js
как файл репозитория. Но в более практических сценариях, если введениеvuex
, то вам не избежать подмодулей, давайте сначала посмотрим на код файла по умолчанию:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
}
})
Так что теперь преобразуйте его, например, сначала разделитеapp
,user
Два модуля, может быть так:
import Vue from 'vue'
import Vuex from 'vuex'
import app from './store/modules/app'
import user from './store/modules/user'
import getters from './store/getters'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
user
},
getters
})
export default store
существуетsrc/
Создать подstore/
содержание:
app module
Может использоваться для хранения состояния приложения, например глобальногоloading
или контролировать глобальный размер сторонних компонентов, таких какelement ui
глобальные компоненты вsize
;
user module
Может использоваться для хранения информации о текущем пользователе;
Конечно, магазин отлично подходит для локального хранилища, здесь мы используемjs-cookie
.
Глобальная загрузка, рациональное использование vue router guard
глобальная загрузка
вышеизложенное закончилосьaxios、vuex
, теперь поговорим о настройке глобального перед объединениемloading
Эффект.
Обычно код пишут перед каждым запросом, как правило, необходимо установитьloading
, закончить после успехаloading
эффект, который заставляет нас писать много повторяющегося кода, если вы не хотите этого делать, вы можете комбинироватьaxios
иvuex
унифицированный.
- Во-первых, говоря
vuex
когда я былsrc/
создалstore
, Сейчасstore/modules/app.js
напиши этоLoading
код эффекта;
const app = {
state: {
requestLoading: 0
},
mutations: {
SET_LOADING: (state, status) => {
// error 的时候直接重置
if (status === 0) {
state.requestLoading = 0
return
}
state.requestLoading = status ? ++state.requestLoading : --state.requestLoading
}
},
actions: {
SetLoading ({ commit }, status) {
commit('SET_LOADING', status)
}
}
}
export default app
- Измените его снова
utils/request.js
import axios from 'axios'
import store from '@/store'
// 创建axios 实例
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
timeout: 10000 // 请求超时时间
})
// request 拦截器
service.interceptors.request.use(
config => {
// 这里可以自定义一些config 配置
// loading + 1
store.dispatch('SetLoading', true)
return config
},
error => {
// 这里处理一些请求出错的情况
// loading 清 0
setTimeout(function () {
store.dispatch('SetLoading', 0)
}, 300)
console.log(error)
Promise.reject(error)
}
)
// response 拦截器
service.interceptors.response.use(
response => {
const res = response.data
// 这里处理一些response 正常放回时的逻辑
// loading - 1
store.dispatch('SetLoading', false)
return res
},
error => {
// 这里处理一些response 出错时的逻辑
// loading - 1
store.dispatch('SetLoading', false)
return Promise.reject(error)
}
)
export default service
- Во-вторых, в
src/components/
Создать подRequestLoading.vue
Компоненты:
<template>
<transition name="fade-transform" mode="out-in">
<div class="request-loading-component" v-if="requestLoading">
<svg-icon icon-class="loading" />
</div>
</transition>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'RequestLoading',
computed: {
...mapGetters([
'requestLoading'
])
}
}
</script>
<style lang='scss' scoped>
.request-loading-component {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
//background-color: rgba(48, 65, 86, 0.2);
background-color: transparent;
font-size: 150px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
z-index: 999999;
}
</style>
Наконец, вapp.vue
можно импортировать.
Приложение: Для облегчения демонстрации инициализация включает в себя проектaxios
,vuex
,vue-router
, в проекте используетсяjs-cookie
,element-ui
Подождите, после этого шага он будет преобразованapp.vue
;
защита маршрутизатора vue
vue-router предоставляет очень удобные хуки, которые позволяют нам выполнять некоторые операции при выполнении переходов маршрутизации, например, общую проверку разрешений.
- Во-первых, вам нужно
src/utils/
Создать подauth.js
, используется для хранения токенов;
import Cookies from 'js-cookie'
const TokenKey = 'project-token'
export function getToken () {
return Cookies.get(TokenKey)
}
export function setToken (token) {
return Cookies.set(TokenKey, token)
}
export function removeToken () {
return Cookies.remove(TokenKey)
}
существуетsrc/utils/
Создать подpermission.js
:
import router from '@/router'
import store from '@/store'
import {
getToken
} from './auth'
import NProgress from 'nprogress' // 进度条
import 'nprogress/nprogress.css' // 进度条样式
import {
Message
} from 'element-ui'
const whiteList = ['/login'] // 不重定向白名单
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
if (to.path === '/login') {
next({
path: '/'
})
NProgress.done()
} else { // 实时拉取用户的信息
store.dispatch('GetUserInfo').then(res => {
next()
}).catch(err => {
store.dispatch('FedLogOut').then(() => {
Message.error('拉取用户信息失败,请重新登录!' + err)
next({
path: '/'
})
})
})
}
} else {
if (whiteList.includes(to.path)) {
next()
} else {
next('/login')
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done() // 结束Progress
})
Nginx try_files и 404
nginx
Конфигурация выглядит следующим образом:
location / {
root /www/vue-project-demo/;
try_files $uri $uri/ /index.html index.htm;
}
try_files
: можно понять, что nginx не обрабатывает ваши запросы на эти url-адреса;
Затем, если сервер не справляется с этим, внешний интерфейс должен выполнить некоторые операции 404 самостоятельно, например следующие:
// router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{ path: '/404', component: () => import('@/views/404') },
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
},
{ path: '*', redirect: '/404' }
]
})
Затем напишите представление 404, и все в порядке.
Часто используемые утилиты
До сих пор,utils/
В каталоге должно бытьauth.js 、permission.js、request.js
;
-
Ну, с некоторыми общими методами, вы можете поставить
utils/common.js
в, унифицированныйinstall
прибытьvue
экземпляр, и поVue.use()
использовать; -
Для некоторых глобальных фильтров еще можно поставить
utils/filters.js
в использованииVue.fileter()
зарегистрироваться в глобале; -
Для некоторых глобальных методов, которые давно не используются, их можно поместить в
utils/index.js
, где использовать гдеimport
mixin уменьшает избыточный код проекта
Просто посмотрите на код, он рухнет....
Используйте cdn, чтобы уменьшить размер упаковки файлов
На этом этапе посмотрите, что я использовал в своем проекте:
Это основные, а как насчет выполнения команды упаковки?Возможно, вы еще ничего не чувствуете в это время, максимальное количество одиночных файлов не превышено800kb
Шерстяная ткань...
я прохожу проектjenkins
Разверните на сервере и посмотрите на доступ:
можно увидеть,chunk-vendors
Загрузка заняла почти 12 секунд, это только при условии, что у фреймворка нет контента, конечно, вы можете сказать, что не можете использовать его в своем проекте.vuex
бесполезныйjs-cookie
, но при итеративном сопровождении проекта меньше, чем сейчас, точно не будет.
Итак, можно ли попробовать некоторые файлы в рабочей среде?cdn
Шерстяная ткань?
Для удобства сравнения оставьте исходный код здесь без изменений (master
ветвь), а затем вырезать ветвь, чтобы изменить оптимизацию (optimize
филиал), приведенный выше код:
// vue.config.js 修改
const path = require('path')
function resolve(dir) {
return path.join(__dirname, './', dir)
}
// cdn预加载使用
const externals = {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios',
'element-ui': 'ELEMENT',
'js-cookie': 'Cookies',
'nprogress': 'NProgress'
}
const cdn = {
// 开发环境
dev: {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
],
js: []
},
// 生产环境
build: {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
],
js: [
'https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js',
'https://cdn.jsdelivr.net/npm/vue-router@3.0.1/dist/vue-router.min.js',
'https://cdn.jsdelivr.net/npm/vuex@3.0.1/dist/vuex.min.js',
'https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js',
'https://unpkg.com/element-ui/lib/index.js',
'https://cdn.bootcss.com/js-cookie/2.2.0/js.cookie.min.js',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js'
]
}
}
module.exports = {
chainWebpack: config => {
// 这里是对环境的配置,不同环境对应不同的BASE_API,以便axios的请求地址不同
config.plugin('define').tap(args => {
const argv = process.argv
const mode = argv[argv.indexOf('--project-mode') + 1]
args[0]['process.env'].MODE = `"${mode}"`
args[0]['process.env'].BASE_API = '"http://47.94.138.75:8000"'
return args
})
/**
* 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改
*/
config.plugin('html').tap(args => {
if (process.env.NODE_ENV === 'production') {
args[0].cdn = cdn.build
}
if (process.env.NODE_ENV === 'development') {
args[0].cdn = cdn.dev
}
return args
})
// svg loader
const svgRule = config.module.rule('svg') // 找到svg-loader
svgRule.uses.clear() // 清除已有的loader, 如果不这样做会添加在此loader之后
svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
svgRule // 添加svg新的loader处理
.test(/\.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
// 修改images loader 添加svg处理
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(resolve('src/icons'))
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
},
// 修改webpack config, 使其不打包externals下的资源
configureWebpack: config => {
const myConfig = {}
if (process.env.NODE_ENV === 'production') {
// 1. 生产环境npm包转CDN
myConfig.externals = externals
}
if (process.env.NODE_ENV === 'development') {
/**
* 关闭host check,方便使用ngrok之类的内网转发工具
*/
myConfig.devServer = {
disableHostCheck: true
}
}
// open: true,
// hot: true
// // https: true,
// // proxy: {
// // '/proxy': {
// // target: 'http://47.94.138.75',
// // // changeOrigin: true,
// // pathRewrite: {
// // '^/proxy': ''
// // }
// // }
// // },
// }
return myConfig
}
}
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- 使用CDN加速的CSS文件,配置在vue.config.js下 -->
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style">
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
<% } %>
<!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="preload" as="script">
<% } %>
<title>vue-project-demo</title>
</head>
<body>
<noscript>
<strong>We're sorry but vue-project-demo doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<div id="app"></div>
<!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
<!-- built files will be auto injected -->
</body>
</html>
окончательное удалениеmain.js
введен вimport 'element-ui/lib/theme-chalk/index.css'
Хорошо, теперь выполнитеbuild
:
Видно, что по сравнению с793.20KB
,61.94k
почти слишком маленький13
раз! ! !
Разверните эту ветку на сервере, особо нечего сказать, просто сравните:
Ускоряйтесь с помощью Gzip
-
Введите сжатие-webpack-плагин:
npm i -D compression-webpack-plugin
Woohoo. Веб-пакет JS.com/plugins/com… -
Исправлять
vue.config.js
, старые правила, самый полный код:
const path = require('path')
const CompressionWebpackPlugin = require('compression-webpack-plugin')
function resolve(dir) {
return path.join(__dirname, './', dir)
}
// cdn预加载使用
const externals = {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios',
'element-ui': 'ELEMENT',
'js-cookie': 'Cookies',
'nprogress': 'NProgress'
}
const cdn = {
// 开发环境
dev: {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
],
js: []
},
// 生产环境
build: {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
],
js: [
'https://cdn.bootcss.com/vue/2.5.21/vue.min.js',
'https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js',
'https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js',
'https://cdn.bootcss.com/axios/0.18.0/axios.min.js',
'https://unpkg.com/element-ui/lib/index.js',
'https://cdn.bootcss.com/js-cookie/2.2.0/js.cookie.min.js',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js'
]
}
}
// 是否使用gzip
const productionGzip = true
// 需要gzip压缩的文件后缀
const productionGzipExtensions = ['js', 'css']
module.exports = {
chainWebpack: config => {
// 这里是对环境的配置,不同环境对应不同的BASE_API,以便axios的请求地址不同
config.plugin('define').tap(args => {
const argv = process.argv
const mode = argv[argv.indexOf('--project-mode') + 1]
args[0]['process.env'].MODE = `"${mode}"`
args[0]['process.env'].BASE_API = '"http://47.94.138.75:8000"'
return args
})
/**
* 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改
*/
config.plugin('html').tap(args => {
if (process.env.NODE_ENV === 'production') {
args[0].cdn = cdn.build
}
if (process.env.NODE_ENV === 'development') {
args[0].cdn = cdn.dev
}
return args
})
// svg loader
const svgRule = config.module.rule('svg') // 找到svg-loader
svgRule.uses.clear() // 清除已有的loader, 如果不这样做会添加在此loader之后
svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
svgRule // 添加svg新的loader处理
.test(/\.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
// 修改images loader 添加svg处理
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(resolve('src/icons'))
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
},
// 修改webpack config, 使其不打包externals下的资源
configureWebpack: config => {
const myConfig = {}
if (process.env.NODE_ENV === 'production') {
// 1. 生产环境npm包转CDN
myConfig.externals = externals
myConfig.plugins = []
// 2. 构建时开启gzip,降低服务器压缩对CPU资源的占用,服务器也要相应开启gzip
productionGzip && myConfig.plugins.push(
new CompressionWebpackPlugin({
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
threshold: 8192,
minRatio: 0.8
})
)
}
if (process.env.NODE_ENV === 'development') {
/**
* 关闭host check,方便使用ngrok之类的内网转发工具
*/
myConfig.devServer = {
disableHostCheck: true
}
}
// open: true,
// hot: true
// // https: true,
// // proxy: {
// // '/proxy': {
// // target: 'http://47.94.138.75',
// // // changeOrigin: true,
// // pathRewrite: {
// // '^/proxy': ''
// // }
// // }
// // },
// }
return myConfig
}
}
-
бежать снова
build
, мы найдемdist/
под всеми.js
и.css
будет еще один.js.gz、.css.gz
Файл, это сжатый файл, который нам нужен, вы можете видеть, что самый большой только18.05KB
, подумайте, будет ли это более захватывающим... -
Конечно, этой штуке тоже нужна серверная поддержка, то есть настройка
nginx
:
gzip on;
gzip_static on;
gzip_min_length 1024;
gzip_buffers 4 16k;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
gzip_vary off;
gzip_disable "MSIE [1-6]\.";
- Перезагрузка после настройки
nginx
:
Если конфигурация прошла успешно, вы можете увидеть, что нагрузка относительно невелика.Gzip
:
существуетresponse headers
будет одинContent-Encoding:gzip
---------------------------- Продолжение следует------------------- ------------