写点什么

vue+webpack+vue-cli

用户头像
关注
发布于: 2021 年 04 月 30 日
1.Vue.component()与 Vue.use()会导致 webpack 打包产生的 chunk-vendors.js 过大会造成首页加首次载缓慢?


Object.values(element).map((e: any)=> {  if (!e.__file && !e.name) return  Vue.component('Ca' + e.name, e)})
复制代码

应该提取基础组件例如高频使用的组件加入劝阻注册

2.用手机访问页面只需要加载当前访问的页面,不需要预加载,怎么处理?
  1. 实现预加载的原理,在 head 里面的 link 标签添加或 rel="preload"与主线并行加载,rel="prefetch"等浏览器空闲时候加载

<head>    <meta charset="utf-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width,initial-scale=1">    <link rel="icon" href="favicon.ico">    <title>20201107</title>    <link href="css/Hello.b6c33b6c.css" rel="prefetch">    <link href="css/Home.6d8963a5.css" rel="prefetch">    <link href="css/about.81902981.css" rel="prefetch">    <link href="js/Hello.785b2111.js" rel="prefetch">    <link href="js/Home.35a910df.js" rel="prefetch">    <link href="js/Home~about~test.106c39ca.js" rel="prefetch">    <link href="js/about.6a93100d.js" rel="prefetch">    <link href="js/test.556b05ca.js" rel="prefetch">    <link href="css/app.d9a200a0.css" rel="preload" as="style">    <link href="css/chunk-vendors.c00f84a3.css" rel="preload" as="style">    <link href="js/app.d87781b6.js" rel="preload" as="script">    <link href="js/chunk-vendors.c2030934.js" rel="preload" as="script">    <link href="css/chunk-vendors.c00f84a3.css" rel="stylesheet">    <link href="css/app.d9a200a0.css" rel="stylesheet"></head>
复制代码


    chainWebpack: config => {        config.plugins.delete('preload');        config.plugins.delete('prefetch');    }
复制代码
3.优化首屏加载速度(减小打包后 app.js 与 chunk-vendors.js),第三方组件按需加载
  1. router 使用懒加载组件,父组件引入子组件也是如下方式

  {    path: '/',    component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')  },
复制代码


@Component({    components: {        Hello:() => import(/* webpackChunkName: "Hello", webpackPrefetch: false */ '../components/HelloWorld.vue')    }})
复制代码

2.提取页面公共资源

  1. vue,vueRouter,使用 html-webpack-externals-plugin, 降低 chunk-vendors.js 包的大小

        plugins: [            new HtmlWebpackExternalsPlugin({                externals: [                    {                        module: 'vue',                        entry: 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js',                        global: 'Vue',                    },                    {                        module: 'vue-router',                        entry: 'https://cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',                        global: 'VueRouter',                    },                    {                        module: 'google-roboto',                        entry: {                          path: 'https://unpkg.com/element-ui/lib/theme-chalk/index.css',                          type: 'css',                        },                      },                                ],            }),        ]
复制代码

3.引用 element-ui 实现按需加载

  1. npm install babel-plugin-component -D

  2. .babelrc 修改为:

{  "plugins": [    [      "component",      {        "libraryName": "element-ui",        "styleLibraryName": "theme-chalk"      }    ]  ]}
复制代码

4.webpack 使用 SplitChunksPlugin 实现公共代码抽离代码抽离

optimization: {    splitChunks: {      chunks: 'async|all', // 模块异步        minSize: 20000,// 20k      minRemainingSize: 0,      minChunks: 1, // 被引用次数,到达多少开始抽离      maxAsyncRequests: 30,      maxInitialRequests: 30,      enforceSizeThreshold: 50000,    },  },
复制代码
4.在项目中写了很多没有用到的代码,打包到了服务器上,浪费了资源加载怎么处理?

使用 Tree Shaking 擦除无用的 JavaScript 和 CSS

  1. vue-cli-service build --mode production 默认开启,动态导入 js 无法檫除

如下

         import('../units/index' /* webpackChunkName: "pl" */).then((content) => {             console.log(content.default())         })
复制代码

2.vue-cli-service build --mode development 则不开启

5.CSS 优化
  1. purgecss-webpack-plugin:删除未使用的 CSS。只在生产环境中执行

const PurgeCSSPlugin = require('purgecss-webpack-plugin')const glob = require('glob')const PATHS = {  src: path.join(__dirname, 'src')}
new PurgeCSSPlugin({ paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),})
复制代码

注意:写在组件里面的 css 并不会被清除掉,通过 @import url('../less.less');可以清除

<style>.style-pl{    color: red;}.head-pl{    position: relative;}
</style>
复制代码

2.mini-css-extract-plugin:将 CSS 提取到单独的文件中。它为每个包含 CSS 的 JS 文件创建一个 CSS 文件。它支持 CSS 和 SourceMap 的按需加载(vuecli 内置了此插件)

chainWebpack(config) {	config.when(process.env.NODE_ENV !== 'development', config => {		config.plugin('extract-css').tap(options => {        	options[0].filename = 'static/css/[name].[hash:8].css'        	return options      })	}}
复制代码
6.安装 sass,目前装以下版本,高版本报错

"node-sass""^4.11.0", "sass-loader""^7.1.0",

7.压缩图片
  1.  image-webpack-loader

        config.module            .rule('graphql')            .test(/\.(gif|png|jpe?g|svg)$/i)            .use('file-loader')            .loader('image-webpack-loader')            .tap(options => {                // 修改它的选项...                return options = {                    mozjpeg: {                        progressive: true,                    },                    // optipng.enabled: false will disable optipng                    optipng: {                        enabled: false,                    },                    pngquant: {                        quality: [0.65, 0.90],                        speed: 4                    },                    gifsicle: {                        interlaced: false,                    },                    // the webp option will enable WEBP                    webp: {                        quality: 75                    }                }            })            .end()
复制代码

注意:出现 Error: Cannot find module 'imagemin-gifsicle'报错,卸掉插件在安装 npm un image-webpack-loader

8.gzip 优化
const CompressionPlugin = require("compression-webpack-plugin");const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg|ttf|woff)(\?.*)?$/i;new CompressionPlugin({  test: productionGzipExtensions,  deleteOriginalAssets: true, // 是否删除原资源}),
复制代码
9.完整配置
const glob = require('glob')const PurgeCSSPlugin = require('purgecss-webpack-plugin')const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');const CompressionPlugin = require("compression-webpack-plugin");const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg|ttf|woff)(\?.*)?$/i;const { join } = require('path')const PATHS = {    src: join(__dirname, 'src')}module.exports = {    publicPath: './',    productionSourceMap: false, // 关掉map    configureWebpack: {        plugins: [            new HtmlWebpackExternalsPlugin({                externals: [                    {                        module: 'vue',                        entry: 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js',                        global: 'Vue',                    },                    {                        module: 'vue-router',                        entry: 'https://cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',                        global: 'VueRouter',                    },                    {                        module: 'google-roboto',                        entry: {                            path: 'https://unpkg.com/element-ui/lib/theme-chalk/index.css',                            type: 'css',                        },                    },                ],            }),            new PurgeCSSPlugin({                paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),            }),            new CompressionPlugin({                test: productionGzipExtensions,                deleteOriginalAssets: true, // 是否删除原资源            }),        ]    },    chainWebpack: config => {        config.plugins.delete('preload');        config.plugins.delete('prefetch');        config.optimization.splitChunks({            chunks: 'all',            minSize: 20000,            minChunks: 1,        });
config.module .rule('image-loader') .test(/\.(gif|png|jpe?g|svg)$/i) .use('file-loader') .loader('image-webpack-loader') .tap(options => { // 修改它的选项... return options = { mozjpeg: { progressive: true, }, // optipng.enabled: false will disable optipng optipng: { enabled: false, }, pngquant: { quality: [0.65, 0.90], speed: 4 }, gifsicle: { interlaced: false, }, // the webp option will enable WEBP webp: { quality: 75 } } }) .end()
} // devServer: { // proxy: { // '/': { //访问路径,可以自己设置, // target: 'http://xxx:8000/', //代理接口,即后端运行所在的端口 // changeOrigin: true, //设置是否跨域 // ws: true, // // pathRewrite: { //访问路径重写 // // '^/activity/babao_dan/save': 'sss' // // } // } // } // }}
复制代码
10.动态导出模块
 const files = require.context(  directory, // 目录,必须写死  (useSubdirectories = true), // 是否递归  (regExp = /^\.\/.*$/), // 匹配文件  (mode = 'sync') // 同步);导出的功能有3个属性:resolve,keys,id。resolve 是一个函数,并返回已解析请求的模块ID。keys 是一个函数,它返回上下文模块可以处理的所有可能请求的数组
sync 直接打包到当前文件,同步加载并执行lazy 延迟加载会分离出单独的 chunk 文件lazy-once 延迟加载会分离出单独的 chunk 文件,加载过下次再加载直接读取内存里的代码。eager 不会分离出单独的 chunk 文件,但是会返回 promise,只有调用了 promise 才会执行代码,可以理解为先加载了代码,但是我们可以控制延迟执行这部分代码/** * @description: 匹配相应组件方法 * @param {any} 文件信息 * @return {any} 组件信息 */function componentFn(files: any) { const components: any = {}; files.keys().forEach((key: string) => { const name = (require('path').basename(key, '.vue') || files(key).default.name).toLocaleLowerCase(); const file = files(key).default || files(key); components[`mr-${name}`] = file; }); return components;}
复制代码


发布于: 2021 年 04 月 30 日阅读数: 44
用户头像

关注

还未添加个人签名 2020.08.05 加入

还未添加个人简介

评论

发布
暂无评论
vue+webpack+vue-cli