Практика оптимизации производительности упаковки проекта Vue2.6.10 (Vue-cli4)

Vue.js

Привет всем, яКагуя такая милая. В этой статье в основном записан мой блог на禁用缓存В случае времени загрузки от восьми-девяти секунд до финала985msПрактика оптимизации может быть достигнута при включенном кэше.138msСкорость доступа , адрес предварительного просмотра:www.cooldream.fun

Мой личный блог используетVue-cli4.1.2 + typescriptПостроить

Структура каталогов проекта выглядит следующим образом

├─ src    //主文件
│  ├─ api    //接口文件夹
|  |  |- config.js    //后端接口地址的配置,将测试、开发、生产环境分开
|  |  └─ user.js      //接口文件,配置了token请求头,具体接口根据需求修改
│  ├─ assets   //资源文件   
│  ├─ components   //公用组件
│  ├─ directive   //vue自定义指令
|  ├─ filters      //存放过滤器文件,自带了手机号加密,手机号格式化,时间日期处理
|  ├─ interceptors    //存放axios拦截器配置,写入了接口调用的loading加载以及http状态码报错拦截
|  ├─ interceptors    //放置公用的接口,对数据进行类型限制
|  ├─ layout      //布局文件,通过子路由渲染方式实现,具体HTML布局根据需求修改  
|  ├─ mixins      //混入文件,配置了一个平滑滚动的方法
|  ├─ plugins     //外部插件文件夹,配置了按需引入的element-ui
|  ├─ reg    //存放正则以及校验的文件夹
|  |  |- reg.ts      //存放正则表达式,自带了传真,邮箱,qq,手机号,银行卡号,固定电话,密码强度校验正则
|  |  └─ validator.ts      //存放element-ui自定义校验,自带了传真,邮箱,qq,手机号,银行卡号,固定电话,密码强度自定义校验
|  ├─ router      //路由文件
|  ├─ store       //vuex全局变量文件
|  |  |- index.ts      //store主文件
|  |  └─ module     //store模块文件夹
|  |  |  └─ user.ts      //存放user相关的全局变量
|  ├─ stylus   //css预处理器文件夹
|  |  |- reset.styl      //样式初始化文件,自带了非标准盒子,a标签清除下划线,清除内外边距,禁止图片拖拽等效果
|  |  └─ color.styl     //颜色变量文件
|  ├─ utils   //公用方法文件夹
|  |  |- area.ts      //存放省市区三级地区的数据
|  |  |- array.ts      //存放数组相关的公用方法,自带了两个元素交换位置,元素前进后退一格,元素置顶或末尾,去重,删除指定元素操作
|  |  └─ object.ts    //存放对象相关的公用方法,自带了对象清空所有值的方法
|  ├─ views   //页面文件夹
|  ├─ main.ts   //主配置文件
|  ├─ babel.config.js   //babel配置文件,写入了element-ui按需加载的配置
|  ├─ package.json   //npm的包管理文件
|  ├─ tsconfig.json   //ts配置文件
|  ├─ vue.config.js   //vue配置文件

1. Закрыть производствоSourceMap

Во-первых, благодаря последней версии строительных лесов.不自带配置文件Теперь сначала создайте новый в корневом каталогеvue.config.jsфайл, закрытьproductionSourceMap,существуетvue.config.jsнапишите следующее в

module.exports = {
    productionSourceMap: false
}

2. Включите сжатие Gzip

Установить плагинcompression-webpack-plugin, включить сжатие кода,npm install --save-dev compression-webpack-plugin, сейчасvue.config.jsКод выглядит следующим образом, однако следует отметить, что gzip также должен быть включен на сервере, чтобы nginx вступил в силу.

// 是否为生产环境
const isProduction = process.env.NODE_ENV !== 'development';

// gzip压缩
const CompressionWebpackPlugin = require('compression-webpack-plugin')

module.exports = {
    productionSourceMap: false,
    configureWebpack: config => {
        // 生产环境相关配置
        if (isProduction) {
            //gzip压缩
            const productionGzipExtensions = ['html', 'js', 'css']
            config.plugins.push(
                new CompressionWebpackPlugin({
                    filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test: new RegExp(
                        '\\.(' + productionGzipExtensions.join('|') + ')$'
                    ),
                    threshold: 10240, // 只有大小大于该值的资源会被处理 10240
                    minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
                    deleteOriginalAssets: false // 删除原文件
                })
            )
        }
    }
}

Открытьnginxв папкеnginx.confфайл, вhttpНапишите в модуле следующее

    # 开启gzip
    gzip on;

    # 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
    gzip_min_length 1k;

    # gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
    gzip_comp_level 2;

    # 进行压缩的文件类型。javascript有多种形式,后面的图片压缩不需要的可以自行删除
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

    # 是否在http header中添加Vary: Accept-Encoding,建议开启
    gzip_vary on;

    # 设置压缩所需要的缓冲区大小     
    gzip_buffers 4 16k;

затем введите командуnginx -s reloadПерезапустите службу nginx.

Если на бэкенде nginx включен gzip, вы можете начать сnetworkсерединаContent-Encodingвидеть вgzip

image.png

3. Включите ускорение CDN (рекомендуемый вариант, хотя CDN работает быстро, но не так стабильно, как локальная упаковка)

Используемый плагин использует ссылку cdn и настраиваетwebpackбуду использоватьCDNПлагины не запакованы, не забудьтеindex.htmlвведен вjsтак же какcss

// 是否为生产环境
const isProduction = process.env.NODE_ENV !== 'development';

// 本地环境是否需要使用cdn
const devNeedCdn = false

// cdn链接
const cdn = {
    // cdn:模块名称和模块作用域命名(对应window里面挂载的变量名称)
    externals: {
        vue: 'Vue',
        vuex: 'Vuex',
        'vue-router': 'VueRouter',
        'marked': 'marked',
        'highlight.js': 'hljs',
        'nprogress': 'NProgress',
        'axios': 'axios'
    },
    // cdn的css链接
    css: [
        'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
    ],
    // cdn的js链接
    js: [
        'https://cdn.bootcss.com/vue/2.6.10/vue.min.js',
        'https://cdn.bootcss.com/vuex/3.1.2/vuex.min.js',
        'https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js',
        'https://cdn.bootcss.com/marked/0.8.0/marked.min.js',
        'https://cdn.bootcss.com/highlight.js/9.18.1/highlight.min.js',
        'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js',
        'https://cdn.bootcss.com/axios/0.19.2/axios.min.js'
    ]
}

module.exports = {
    chainWebpack: config => {
        // ============注入cdn start============
        config.plugin('html').tap(args => {
            // 生产环境或本地需要cdn时,才注入cdn
            if (isProduction || devNeedCdn) args[0].cdn = cdn
            return args
        })
        // ============注入cdn start============
    },
    configureWebpack: config => {
        // 用cdn方式引入,则构建时要忽略相关资源
        if (isProduction || devNeedCdn) config.externals = cdn.externals
    }
}

Далее, вindex.htmlиспользуется вCDNссылка на

<!DOCTYPE html>
<html lang="en" style="width: 100%;height: 100%;">
  <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文件 -->
    <% for (var i in htmlWebpackPlugin.options.cdn &&
    htmlWebpackPlugin.options.cdn.css) { %>
    <link
            href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"
            rel="stylesheet"
    />
    <% } %>
    <!-- 使用CDN的CSS文件 -->

    <title>CoolDream</title>
  </head>
  <body style="width: 100%;height: 100%;">
    <noscript>
      <strong>We're sorry but blog doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->

    <!-- 使用CDN的JS文件 -->
    <% for (var i in htmlWebpackPlugin.options.cdn &&
    htmlWebpackPlugin.options.cdn.js) { %>
    <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
    <% } %>
    <!-- 使用CDN的JS文件 -->

  </body>
</html>

После упаковки кидайте на сервер, открывайте в сети инструменты разработчика, если увидитеhttpпроситьcdn, то настройка прошла успешно, как показано на рисунке

image.png

4. Сжатие кода

Сначала установите плагинnpm i -D uglifyjs-webpack-plugin

Затем импортируйте зависимости вверху

// 代码压缩
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

существуетconfigureWebpack Внедрить сжатие кода в модулях

// 代码压缩
config.plugins.push(
    new UglifyJsPlugin({
        uglifyOptions: {
            //生产环境自动删除console
            compress: {
                drop_debugger: true,
                drop_console: true,
                pure_funcs: ['console.log']
            }
        },
        sourceMap: false,
        parallel: true
    })
)

5. Публичный код извлекается и записывается вconfigureWebpackмодуль

// 公共代码抽离
config.optimization = {
    splitChunks: {
        cacheGroups: {
            vendor: {
                chunks: 'all',
                test: /node_modules/,
                name: 'vendor',
                minChunks: 1,
                maxInitialRequests: 5,
                minSize: 0,
                priority: 100
            },
            common: {
                chunks: 'all',
                test: /[\\/]src[\\/]js[\\/]/,
                name: 'common',
                minChunks: 2,
                maxInitialRequests: 5,
                minSize: 0,
                priority: 60
            },
            styles: {
                name: 'styles',
                test: /\.(sa|sc|c)ss$/,
                chunks: 'all',
                enforce: true
            },
            runtimeChunk: {
                name: 'manifest'
            }
        }
    }
}

6. Сжатие изображения ()

1. Используйте плагин для сжатия изображений

  • Сначала установите плагинnpm install image-webpack-loader --save-dev
  • существуетchainWebpackДобавьте следующий код в
// ============压缩图片 start============
config.module
    .rule('images')
    .use('image-webpack-loader')
    .loader('image-webpack-loader')
    .options({ bypassOnDebug: true })
    .end()
// ============压缩图片 end============

2. Хранить статические ресурсы в облаке, облако Qiniu для личного пользования, объектное хранилище для хранения файлов, использоватьcdnУскорение обеспечивает более быстрый доступ к сохраненным статическим ресурсам.(推荐,速度能快挺多)

  • Я лично подал заявку на Qiniu Cloud, и у меня есть 10 ГБ свободного места для аутентификации по реальному имени и 10 ГБ бесплатного трафика каждый месяц.Однако, если я не привяжу доменное имя, у меня будет только 30-дневная возможность использования. Я привязываю свое доменное имя для разрешения и переноса DNS. Конкретная операция может относиться к этому блогу,Блог Woohoo.cn на.com/ma указал/afraid/…

7. Оптимизация каркаса экрана первого экрана (необязательно, см. ваши фактические потребности)

1. Установите плагин

npm install vue-skeleton-webpack-plugin --save

2. Создайте новый файл каркаса экрана

существуетsrcпод новымSkeletonпапка, где новыеindex.jsтак же какindex.vue, напишите в нем следующее, где экран каркасаindex.vueПожалуйста, отредактируйте стиль страницы самостоятельно

//index.js
import Vue from 'vue'
// 创建的骨架屏 Vue 实例
import skeleton from './index.vue';

export default new Vue({
    components: {
        skeleton
    },
    template: '<skeleton />'
});
//index.vue
<template>
    <div class="skeleton-box">
        loading
    </div>
</template>

<script lang="ts">
    import {Vue,Component} from "vue-property-decorator";

    @Component({
        name:'Skeleton'
    })
    export default class Skeleton extends Vue{

    }
</script>

<style lang="stylus" scoped>
.skeleton-box{
    font-size 24px
    display flex
    align-items center
    justify-content center
    width 100vh
    height 100vh
}
</style>

3. Вvue.config.jsСкелетный экран средней конфигурации

существуетvue.config.jsнапишите следующее в

//骨架屏渲染
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin')

//path引入
const path = require('path')

//configureWebpack模块中写入内容
// 骨架屏渲染
config.plugins.push(
    new SkeletonWebpackPlugin({
        webpackConfig: {
            entry: {
                app: path.join(__dirname,'./src/components/Skeleton/index.js')
            }
        }
    })
)

8. Отключите предварительную загрузку модулей

vue-cliВключено по умолчаниюprefetch(предварительная загрузка модулей), чтобы заранее получать контент, к которому пользователи могут получить доступ в будущем.

Если вы хотите как можно скорее отобразить первый экран, вы можете игнорировать скорость следующих страниц, тогда вы можете удалить этот модуль.

config.plugins.delete('prefetch')

Итак, конечный конфигурационный файл выглядит следующим образом (закомментирован для отключения предзагрузки модулей, распечатывать при необходимости)

// 是否为生产环境
const isProduction = process.env.NODE_ENV !== 'development';

// 代码压缩
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

// gzip压缩
const CompressionWebpackPlugin = require('compression-webpack-plugin')

//骨架屏渲染
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin')

//path引入
const path = require('path')

// 本地环境是否需要使用cdn
const devNeedCdn = false

// cdn链接
const cdn = {
    // cdn:模块名称和模块作用域命名(对应window里面挂载的变量名称)
    externals: {
        vue: 'Vue',
        vuex: 'Vuex',
        'vue-router': 'VueRouter',
        'marked': 'marked',
        'highlight.js': 'hljs',
        'nprogress': 'NProgress',
        'axios': 'axios'
    },
    // cdn的css链接
    css: [
        'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
    ],
    // cdn的js链接
    js: [
        'https://cdn.bootcss.com/vue/2.6.10/vue.min.js',
        'https://cdn.bootcss.com/vuex/3.1.2/vuex.min.js',
        'https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js',
        'https://cdn.bootcss.com/marked/0.8.0/marked.min.js',
        'https://cdn.bootcss.com/highlight.js/9.18.1/highlight.min.js',
        'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js',
        'https://cdn.bootcss.com/axios/0.19.2/axios.min.js'
    ]
}

module.exports = {
    productionSourceMap: false,
    chainWebpack: config => {
        // ============预先加载模块 关闭============
        //   config.plugins.delete('prefetch')     
        // ============预先加载模块 关闭============
        // ============注入cdn start============
        config.plugin('html').tap(args => {
            // 生产环境或本地需要cdn时,才注入cdn
            if (isProduction || devNeedCdn) args[0].cdn = cdn
            return args
        })
        // ============注入cdn start============

        // ============压缩图片 start============
        config.module
            .rule('images')
            .use('image-webpack-loader')
            .loader('image-webpack-loader')
            .options({ bypassOnDebug: true })
            .end()
        // ============压缩图片 end============
    },
    configureWebpack: config => {
        // 用cdn方式引入,则构建时要忽略相关资源
        if (isProduction || devNeedCdn) config.externals = cdn.externals

        // 生产环境相关配置
        if (isProduction) {
            //gzip压缩
            const productionGzipExtensions = ['html', 'js', 'css']
            config.plugins.push(
                new CompressionWebpackPlugin({
                    filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test: new RegExp(
                        '\\.(' + productionGzipExtensions.join('|') + ')$'
                    ),
                    threshold: 10240, // 只有大小大于该值的资源会被处理 10240
                    minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
                    deleteOriginalAssets: false // 删除原文件
                })
            )

            // 代码压缩
            config.plugins.push(
                new UglifyJsPlugin({
                    uglifyOptions: {
                        //生产环境自动删除console
                        compress: {
                            drop_debugger: true,
                            drop_console: true,
                            pure_funcs: ['console.log']
                        }
                    },
                    sourceMap: false,
                    parallel: true
                })
            )
        }

        // 骨架屏渲染
        config.plugins.push(
            new SkeletonWebpackPlugin({
                webpackConfig: {
                    entry: {
                        app: path.join(__dirname,'./src/components/Skeleton/index.js')
                    }
                }
            })
        )

        // 公共代码抽离
        config.optimization = {
            splitChunks: {
                cacheGroups: {
                    vendor: {
                        chunks: 'all',
                        test: /node_modules/,
                        name: 'vendor',
                        minChunks: 1,
                        maxInitialRequests: 5,
                        minSize: 0,
                        priority: 100
                    },
                    common: {
                        chunks: 'all',
                        test: /[\\/]src[\\/]js[\\/]/,
                        name: 'common',
                        minChunks: 2,
                        maxInitialRequests: 5,
                        minSize: 0,
                        priority: 60
                    },
                    styles: {
                        name: 'styles',
                        test: /\.(sa|sc|c)ss$/,
                        chunks: 'all',
                        enforce: true
                    },
                    runtimeChunk: {
                        name: 'manifest'
                    }
                }
            }
        }
    }
}

8. Кэш конфигурации nginx

Это также может повысить скорость доступа к веб-сайту (хотя это немного отличается от темы упаковки внешнего интерфейса, но все же очень полезно для разработки внешнего интерфейса вашего личного веб-сайта блога!) Напишите содержимое в http-модуль nginx.conf

     # 设置缓存路径并且使用一块最大100M的共享内存,用于硬盘上的文件索引,包括文件名和请求次数,每个文件在1天内若不活跃(无请求)则从硬盘上淘汰,硬盘缓存最大10G,满了则根据LRU算法自动清除缓存。
    proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=imgcache:100m inactive=1d max_size=10g;

Затем запишите содержимое в модуль serve nginx.conf, сохраните конфигурацию,nginx -s reloadПерезапустите службу, чтобы увидеть эффект

location ~* ^.+\.(css|js|ico|gif|jpg|jpeg|png)$ {
 log_not_found off;
 # 关闭日志
 access_log off;
 # 缓存时间7天
 expires 7d;
 # 源服务器
 proxy_pass http://localhost:8888;
 # 指定上面设置的缓存区域
 proxy_cache imgcache;
 # 缓存过期管理
 proxy_cache_valid 200 302 1d;
 proxy_cache_valid 404 10m;
 proxy_cache_valid any 1h;
 proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
 }

Эта статья в основном касаетсяWoohoo.Краткое описание.com/afraid/476387 от 7…

Кроме того, еще раз делюсь сборкой, которую я построил на основеVue2.6.10+TypescriptПостроенный пустой проект, включая инициализацию стиля css, а также базовые общие аксиомы, vue-router, модульное использование vuex, element-ui был импортирован и настроен по мере необходимости, а также перехватчик axios, глобальная загрузка axios загрузка запросов, маршрутизация Ленивая загрузка компонентов, а также базовая инкапсуляция URL для различных сред, также поставляется с некоторыми общими методами, а также введение cdn, включая оптимизацию упаковки, сжатие кода, сжатие изображений, карту закрытия и другие оптимизации упаковки. , Что касается использования ts, Чтобы использовать модификаторы, в Home.vue я перечислил часто используемые методы, и адрес:GitHub.com/Джек-звезда-Т…