>  기사  >  웹 프론트엔드  >  vue-admin-template을 사용한 최적화 단계에 대한 자세한 설명

vue-admin-template을 사용한 최적화 단계에 대한 자세한 설명

php中世界最好的语言
php中世界最好的语言원래의
2018-05-28 15:06:024044검색

이번에는 vue-admin-template을 사용하기 위한 최적화 단계에 대해 자세히 설명하고, vue-admin-template을 사용하여 최적화할 때 주의사항은 무엇인지 살펴보겠습니다. .

머리말

회사에는 백엔드 관리 시스템을 갖춘 여러 프로젝트가 있습니다. 개발을 촉진하기 위해 우리는 Vue에서 인기 있는 백엔드 템플릿을 개발용 기본 템플릿으로 선택했습니다. 그러나 사용을 시작했을 때 작성자는 이를 최적화하지 않았습니다. 프로젝트가 온라인에 접속했을 때 패키지 파일이 매우 크고 한 공급업체의 볼륨이 770k라는 것을 발견했습니다(아래 그림은 기본 템플릿입니다. 패키지 파일 정보 추가 없이):

webpack-bundle-analyzer 분석을 통해 얻을 수 있습니다. 볼륨은 주로 Ele.me UI(볼륨은 500k)에서 가져옵니다. 분할 구성 요소를 부분적으로 도입하지 않으면 webpack이 전체 구성 요소 라이브러리를 패키징하게 됩니다. 두 번째는 80k 크기의 vue 자체입니다. webpack-bundle-analyzer 进行分析可得,体积主要来源于饿了么UI(体积为 500k),因为没对其进行部分引入拆分组件,导致 webpack 把整个组件库都打包进去了。其次就是 vue 本身,体积也达到了 80k 之大。

所以,对其进行打包优化,是一件刻不容缓的事情。

优化

优化主要目的有:

  1. 加快资源加载速度,减少用户等待的时间和首页白屏时间,提高用户体验。

  2. 加快打包速度,不要将时间浪费在等待打包上。

解决第一个问题,很多人都会想到资源文件放在 CDN 上就好了,没错,这次我们就是通过 CDN 来解决加载问题。

CDN - 提高加载速度

像 vue, element ui 这些比较成熟的框架/组件库,一般都有免费、高速、公共的 cdn 供开发者使用,鉴于大部分用户均在国内,所以这次使用了 bootcdn 这个库。该库热门资源比较齐全,各个版本都有,而且国内访问速度很快,简直是开发者的福音。

index.html 中引入 vue 和 饿了么组件。

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>vue-admin-template</title>
  <!-- 同时也要引入对应版本的 css -->
  <link href="https://cdn.bootcss.com/element-ui/2.3.2/theme-chalk/index.css" rel="external nofollow" rel="stylesheet">
 </head>
 <body>
  <p id="app"></p>
  <!-- built files will be auto injected -->
  <!-- 先引入 Vue -->
  <script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
  <!-- 引入组件库 -->
  <script src="https://cdn.bootcss.com/element-ui/2.3.2/index.js"></script>
  <script src="https://cdn.bootcss.com/element-ui/2.3.2/locale/zh-CN.min.js"></script>
 </body>
</html>

因为依赖是从外部引入的,所以需要告知 webpack 在打包时,依赖的来源。

修改 webpack.base.conf.js

module.exports = {
 ...
 externals: {
  vue: 'Vue',
  'element-ui':'ELEMENT'
 }
}

再一次打包,确实能极大的压缩了打包的体积,从 700k 骤减至 130k:

但是随之而来的就有问题了:

明明我在本地开发,但是由于引入了线上的生产版本的 vue 文件,因此 vue-dev-tools 就不能进行调试。

因此,我们需要再次调整一下 webpack 的配置,webpack.base.conf.js,而且 webpack 注入的 js 总是在最后面的,因此,我们需要 html-webpack-include-assets-plugin 帮忙在注入 app.js 后,再注入相对应的组件库 :

const HtmlWebpackIncludeAssetsPlugin = require('html-webpack-include-assets-plugin')
const externals = {
 // 因为打包时,还没注入,所以这里要去掉。
 // 'element-ui':'ELEMENT'
}
// 生产环境中使用生产环境的 vue
// 开发环境继续使用本地 node_modules 中的 vue
if (process.env.NODE_ENV === 'production') {
 externals['vue'] = 'Vue'
 // 如发现打包时依旧将 element-ui 打包进入 vendor,可以在打包时将其加入外部依赖。
 externals['element-ui'] = 'ELEMENT'
}
// 生产环境默认注入 vue 
// 开发环境中不注入
const defaultJS = process.env.NODE_ENV === 'production' ? [{ path: 'https://cdn.bootcss.com/vue/2.4.2/vue.min.js', type: 'js' }] : []
const plugins = [
 new HtmlWebpackIncludeAssetsPlugin({
   assets: defaultJS.concat([
    { path: 'https://cdn.bootcss.com/element-ui/2.3.2/index.js', type: 'js' },
    { path: 'https://cdn.bootcss.com/element-ui/2.3.2/locale/zh-CN.min.js', type: 'js' },
   ]),
   // 是否在 webpack 注入的 js 文件后新增?true 为 append, false 为 prepend。
   // 生产环境中,这些 js 应该先加载。
   append: process.env.NODE_ENV !== 'production',
   publicPath: '',
  })
]
module.exports = {
 ...
 externals,
 plugins,
 ...
}

OK,这时候,既能兼顾打包后的体积大小,也能在开发模式中使用 vue-dev-tool 进行调试。

DLL - 提高打包速度

经常打包的前端会发现,很多时候,我们为了修复某些bug(如 promise 在 ie Safari 下的 bug),而新引入了一个 polyfill,然而,打包完后发现,vendor 的 hash 值变了,而整个 vendor 只新加了一个 es6-promise

그러니까, 한번 해보세요 패키징 최적화가 시급한 문제입니다. 🎜🎜🎜🎜Optimization🎜🎜🎜🎜최적화의 주요 목적은 다음과 같습니다. 🎜
  1. 🎜리소스 로딩 속도를 높이고 사용자 대기 시간을 줄이며 홈페이지 흰색 화면 시간을 절약하고 사용자 경험을 향상시킵니다. 🎜
  2. 🎜포장 속도를 높이고 포장을 기다리는 데 시간을 낭비하지 마세요. 🎜
🎜첫 번째 문제를 해결하기 위해 많은 사람들은 리소스 파일을 CDN에 배치할 수 있다고 생각할 것입니다. 네, 이번에는 CDN을 통해 로딩 문제를 해결하겠습니다. 🎜🎜🎜🎜CDN - 로딩 속도 향상🎜🎜🎜🎜vue 및 element ui와 같은 보다 성숙한 프레임워크/구성 요소 라이브러리에는 일반적으로 대부분의 사용자가 중국에 있다는 점을 고려하여 개발자가 사용할 수 있는 무료 고속 공개 CDN이 있습니다. , 그래서 이번에는 bootcdn 라이브러리를 사용했습니다. 이 라이브러리의 인기 있는 리소스는 비교적 완벽하고 다양한 버전으로 제공되며 국내 액세스 속도가 매우 빠르다는 점은 개발자에게 좋은 소식입니다. 🎜🎜vue 및 Ele.me 구성 요소를 index.html에 도입하세요. 🎜
const webpack = require('webpack');
const path = require('path');
const vueLoaderConfig = require('./vue-loader.conf')
const utils = require('./utils')
function resolve(dir) {
  return path.join(dirname, '..', dir)
}
const vendor = [
  // 'vue/dist/vue.runtime.esm.js', // 由于 vue 在生产环境中使用的是 cdn 引入,所以也无需提前打包进 dll
  // 'raven-js', // 前端监控,若无此需求,可以忽略。
  'es6-promise', // 修复 promise 中某些 bug。
  'vue-router',
  'js-cookie',
  'axios',
  'vuex',
];
const webpackConfig = {
  context: dirname,
  output: {
    path: path.join(dirname, '../static/js/'),
    filename: '[name].dll.js',
    library: '[name]_[hash]',
  },
  entry: {
    vendor
  },
  plugins: [
    new webpack.DllPlugin({
      context: dirname,
      path: path.join(dirname, '.', '[name]-manifest.json'),
      name: '[name]_[hash]',
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
       warnings: false
      },
      sourceMap: true,
      // parallel: true
    })
  ],
  module: {
    rules: [{
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  }
};
module.exports = webpackConfig
🎜종속성은 외부에서 유입되기 때문에 웹팩 패키징 시 종속성 소스를 알려줘야 합니다. 🎜🎜 webpack.base.conf.js 수정: 🎜
{
  "scripts": {
    ...
    "build:dll": "webpack --config build/webpack.dll.conf.js",
    ...
  }
}
🎜다시 압축하면 패키지 크기가 700k에서 130k로 크게 압축될 수 있습니다. 🎜🎜🎜🎜하지만 문제가 있습니다:🎜 🎜 🎜🎜분명히 로컬에서 개발을 하고 있지만, 온라인 제작의 도입으로 인해 vue 파일 버전에서는 vue-dev-tools를 디버깅할 수 없습니다. 🎜🎜따라서 webpack 구성을 다시 조정해야 하는데, webpack.base.conf.js이고, webpack에 의해 주입된 js는 항상 마지막에 있으므로 html-webpack이 필요합니다 - include-assets-pluginapp.js를 삽입한 다음 해당 구성 요소 라이브러리를 삽입하는 데 도움이 됩니다. 🎜
yarn build:dll
yarn run v1.5.1
$ webpack --config build/webpack.dll.conf.js
Hash: f6894dff019b2e0734af
Version: webpack 3.10.0
Time: 1295ms
     Asset   Size Chunks       Chunk Names
vendor.dll.js 62.6 kB    0 [emitted] vendor
  [8] dll vendor 12 bytes {0} [built]
  + 32 hidden modules
✨ Done in 1.89s.
🎜이제 패키지 크기를 고려할 수 있습니다. 또한 개발 모드에서 디버깅하려면 vue-dev-tool을 사용하세요. 🎜🎜🎜🎜DLL - 패키징 속도 향상 🎜🎜🎜🎜 패키징을 자주 하는 프런트 엔드에서는 특정 버그(예: IE Safari의 Promise 버그)를 수정하기 위해 새로운 폴리필을 도입합니다. 완료 후 벤더의 해시 값이 변경되었으며 전체 벤더가 es6-promise라는 새 종속성을 추가했을 뿐이지만 지불된 대가는 이전에 패키지된 벤더를 폐기해야 한다는 것입니다. . 사용자가 다시 방문하면 새로운 공급업체를 다시 가져와야 하는데 이는 약간 비용이 많이 듭니다. 🎜🎜이때 dllPlugin 패키징을 사용하면 장점이 있습니다. 일부 기본 종속 모듈을 먼저 함께 패키징할 수 있습니다. 공식적으로 패키징할 때 이러한 모듈을 건너뛰고 더 이상 공급업체에 반복적으로 패키징할 수 없습니다. 이렇게 하면 패키징 속도가 향상되고 공급업체의 규모도 줄어듭니다. 🎜

如,后台管理系统基础模块基本有以下几个:

  1. axios: ajax 请求。

  2. vuex: 全局状态管理。

  3. js-cookie: 前端处理 cookie

  4. vue-router: 路由管理。

这四个基础模块几乎是必须的,那么可以先提取出来。

step 1 打包基础模块

先在 build 文件夹下新建一个用于打包 dll 的配置文件 webpack.dll.conf.js

const webpack = require('webpack');
const path = require('path');
const vueLoaderConfig = require('./vue-loader.conf')
const utils = require('./utils')
function resolve(dir) {
  return path.join(dirname, '..', dir)
}
const vendor = [
  // 'vue/dist/vue.runtime.esm.js', // 由于 vue 在生产环境中使用的是 cdn 引入,所以也无需提前打包进 dll
  // 'raven-js', // 前端监控,若无此需求,可以忽略。
  'es6-promise', // 修复 promise 中某些 bug。
  'vue-router',
  'js-cookie',
  'axios',
  'vuex',
];
const webpackConfig = {
  context: dirname,
  output: {
    path: path.join(dirname, '../static/js/'),
    filename: '[name].dll.js',
    library: '[name]_[hash]',
  },
  entry: {
    vendor
  },
  plugins: [
    new webpack.DllPlugin({
      context: dirname,
      path: path.join(dirname, '.', '[name]-manifest.json'),
      name: '[name]_[hash]',
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
       warnings: false
      },
      sourceMap: true,
      // parallel: true
    })
  ],
  module: {
    rules: [{
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  }
};
module.exports = webpackConfig

然后在 package.json 中加入一条命令:

{
  "scripts": {
    ...
    "build:dll": "webpack --config build/webpack.dll.conf.js",
    ...
  }
}

执行 yarn build:dll 或者 npm run build:dll 即可完成打包 dll。执行完成后:

yarn build:dll
yarn run v1.5.1
$ webpack --config build/webpack.dll.conf.js
Hash: f6894dff019b2e0734af
Version: webpack 3.10.0
Time: 1295ms
     Asset   Size Chunks       Chunk Names
vendor.dll.js 62.6 kB    0 [emitted] vendor
  [8] dll vendor 12 bytes {0} [built]
  + 32 hidden modules
✨ Done in 1.89s.

同时,可以在 build 目录下,找到各个模块对应关系文件 vendors-manifest.jsonstatic/js 下的 vendor.dll.js

step 2 页面中引入 vendor

打包后的 dll 文件需要手动在 index.html 引入:

<p id="app"></p>
<!-- built files will be auto injected -->
<script src="static/js/vendors.dll.js"></script>

step 3 告诉 webpack 使用 dllPlugin 进行打包

修改 build/webpack.prod.conf.js:

module.exports = {
  plugins: [
    ...
    new webpack.DllReferencePlugin({
      context: dirname,
      manifest: require('./vendor-manifest.json')
    }),
    ...
  ]
}

再次打包:

$ yarn build:report
yarn run v1.5.1
$ npm_config_report=true node build/build.js
Hash: b4ff51852866ed865cfd
Version: webpack 3.10.0
Time: 6532ms
                       Asset    Size Chunks       Chunk Names
     static/js/manifest.42b9584a653aec2b9c5e.js   1.5 kB    5 [emitted] manifest
             static/img/404.a57b6f3.png  98.1 kB     [emitted]
        static/js/1.9e4133a25808e2101dd3.js    1 kB    1 [emitted]
        static/js/2.2a8a8e01c51473fab882.js  4.34 kB    2 [emitted]
      static/js/vendor.c7b076ef3341d4711402.js  39.4 kB    3 [emitted] vendor
       static/js/app.6d52c7a5bf1bacb5cc85.js  21.4 kB    4 [emitted] app
        static/js/0.cbc645864aab28ae8055.js  15.3 kB    0 [emitted]
static/css/app.1b30f8eba210e245a5f96d7bf0d6fb6c.css   7.6 kB    4 [emitted] app
                    favicon.ico  67.6 kB     [emitted]
                     index.html 986 bytes     [emitted]
              static/js/vendor.dll.js  62.6 kB     [emitted]
 Build complete.
 Tip: built files are meant to be served over an HTTP server.
 Opening index.html over file:// won't work.

发现 vendor 现在只有 40k 的体积,减少了一半的体积,而且打包速度也快了 2s,而相对于最开始的基础模板,打包速度快了 12s,这是很让人欣慰。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

如何使用v-model与promise两种方式实现vue弹窗组件

怎样使用Vue+Jwt+SpringBoot+Ldap完成登录认证

위 내용은 vue-admin-template을 사용한 최적화 단계에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.