Резюме рефакторинга проекта vue 2022 года

внешний интерфейс Vue.js
Резюме рефакторинга проекта vue 2022 года

"Что загорится в 2022 году? Чему научиться? Эта статья участвует«Поговорим о технологических тенденциях 2022 года»Требуют документов"

Основное содержание этой статьи

  1. Для старых проектов мои шаги по обновлению webpack.
  2. Основываясь на позиционировании продукта и тенденции развития бизнеса проекта, с чего я могу начать и подумать при рефакторинге.

Эта статья была исправлена ​​во время итерации и оптимизации проекта, поэтому на это ушёл один год. Если это может вам помочь, я надеюсь, что вы можете поставить мне большой палец вверх 👍💗, ваш большой палец вверх - лучшее подтверждение моего письма! Спасибо 🙏

Предыстория и решения

Поскольку продукт компании заключается в размещении одного и того же типа программного обеспечения для бизнеса на разных платформах электронной коммерции, недавно открытый проект заключается в переносе старого кода, его удалении и хранении на полке. Поэтому файловая директория разбросана, введение и экспорт запутаны, код избыточен, а стиль недостаточно однообразен. Эти ошибки приводят к очень низкой читабельности и ремонтопригодности кода, множеству конфликтов стилей и множеству странных и трудно воспроизводимых ошибок. Планирую провести трансформацию и оптимизацию проекта в итеративную заливку котлована. Мои шаги решения следующие:

  • Первый шаг: понять основной бизнес (около трех месяцев), обратиться за советом к клиентам при исполнении служебных обязанностей и понять привычки пользователя и стиль позиционирования нашего программного обеспечения. Провели детальное исследование конкурирующих продуктов того же типа (около восьми, наш софт справляется хорошо), и проанализировали недостатки и преимущества наших продуктов. В то же время активно общайтесь с продуктом о направлении развития и плане более поздней стадии проекта. Я чувствую, что когда я взялся за проект, функций было всего 20% от плана, и было еще много возможностей для улучшения. Этот процесс занял около полугода.
  • Шаг 2: Из-за путаницы в каталоге проекта я сначала разделяю каталог проекта в соответствии с функциональными модулями и сопоставляю путь маршрутизации маршрутизатора с путем к файлу, что способствует последующему поиску модуля.
  • Шаг 3: Унифицируйте ввод основных ресурсов и общедоступных ресурсов, что способствует управлению и обслуживанию более поздних ресурсов, и нет необходимости повторять введение кода. Например, введена общедоступная запись CSS для CSS, а общедоступные переменные можно использовать глобально через загрузчик, и их больше нельзя импортировать вручную. Используйте динамическую загрузку шрифтов и удалите локально сохраненные файлы svg.
  • Шаг 4: Поскольку версия проекта webpack 2, и она полностью написана от руки, учитывая поддержку коллег в более позднем периоде и метод трансформации моего запланированного пошагового итеративного обновления, я не использовал vue-cli , но также использовал полный почерк. Конкретные шаги обновления также описаны ниже.
  • Шаг 5: Инкапсуляция логики повторного использования в рамках проекта и оптимизация логики внутреннего кода. Поскольку наш проект имеет дело с b-end клиентами и запросов к данным много, я написал модель со списком запросов, пейджинга и функций поиска, что очень удобно для работы с vuex.

Обновление веб-пакета проекта

Шаги настройки

Сначала закомментируйте весь код входного файла main.js, создайте папку в корневом каталоге: webpack (папка для упаковки скриптов), создайте webpack.common.js (общая конфигурация веб-пакета), webpack.development в папке веб-пакета. js (скрипт настройки в среде разработки webpack), webpack.product.js (скрипт настройки в производственной среде webpack) три файла.

  1. Внесите простейший файл .vue в main.js, только шаблон шаблона, настройте vue-loader, чтобы проект мог нормально работать. Напишите командную строку в скрипте script:
{
    "dev": "webpack-dev-server  ./webpack/webpack.common.js --mode='development'",    
    "build": "webpack --config ./webpack/webpack.common.js  --mode='production'"
  }
  1. Напишите код js в файле .vue, настройте babel и заставьте проект работать нормально.
  2. Напишите код css и less в файле .vue, настройте css и less и заставьте проект работать нормально.
  3. Добавьте изображения, шрифты и т. д. в файл .vue, настройте статические ресурсы и заставьте проект работать нормально.
  4. Добавляйте в файл app.vue только простые компоненты, а затем попробуйте добавить страницу, чтобы проект работал нормально. На этом базовая конфигурация проекта завершена.
  5. Различать переменные среды, упаковывать и настраивать команды сценариев отдельно и оптимизировать сценарии упаковки

Упаковка ресурсов

конфигурация vue

vue-loader: позволяет использовать имяКомпоненты одного файла (SFC)Создавайте компоненты Vue в формате

npm i -D vue-loader

конфигурация модулей

const { VueLoaderPlugin } = require('vue-loader')

{
    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: '[name].[chunkhash].js',
        chunkFilename: '[name].[chunkhash].js',
        publicPath: '/'
    },
    plugins: [
        new VueLoaderPlugin(),
    ],
    module: {
      rules: [
            {
                test: /\.vue$/,
                use: [
                    {
                    loader: 'cache-loader'
                    },
                    {
                    loader: 'vue-loader',
                    options: {
                        transformAssetUrls: {
                        video: ['src', 'poster'],
                        source: 'src',
                        img: 'src',
                        image: ['xlink:href', 'href'],
                        use: ['xlink:href', 'href']
                        },
                        cssSourceMap: true,
                        hotReload: true,
                        compilerOptions: {
                        preserveWhitespace: true
                        }
                    }
                    }
                ],
                exclude: /node_modules/
            },
        ]
    },
}

проверять: Введите командную строку в терминалnpm run buildОб ошибках не сообщается, как показано на следующем рисунке в distimage.png

вавилонская конфигурация

@babel/core: Анализировать код js в ast, что удобно каждому плагину для анализа синтаксиса соответствующей обработки
@babel/cli: ДаbabelПредоставленный инструмент командной строки для компиляции исходного кода в командной строке.
babel-loader: При упаковке с помощью Webpack используйтеBabelБудуES6Преобразуйте код в версию ES5, включите кешированиеcacheDirectory:true, вы можете увидеть файл кеша в node_modules/.cache
@babel/preset-env: вы можете автоматически преобразовать код ES2015+ в es5 в соответствии с настроенным целевым браузером или операционной средой, настроитьuseBuiltIns:trueМожет быть импортирован по запросу. настроитьcorejs:3Указывает версию corejs.
core-js: это полифилл для стандартной библиотеки JavaScript, максимально модульный, что позволяет вам выбирать нужную вам функциональность.

Справочные статьи:# Схема реализации совместимости с Babel

npm install --save-dev @babel/core @babel/cli @babel/preset-env babel-loader @babel/plugin-transform-runtime

.babelrc конфигурация

{
    "presets": [
        ["@babel/preset-env", {
            "useBuiltIns": "usage",
            "corejs": 3,
            "targets": {
              "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
            }
          }]
    ],
    "plugins": [
      "@babel/plugin-transform-runtime"
    ]
}

конфигурация модуля

{
    test: /\.js$/,
    use: [
      {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
          babelrc: true,
          cacheDirectory: true // 启用缓存
        }
      }
    ],
    exclude: /node_modules/
}

"babel": "babel src/index.js --out-dir dist"команда для компиляции тестового файла src/index.js
npm run babelПроверка результата после упаковки image.png

css

vue-style-loader: Анализировать код js в ast, что удобно каждому плагину для анализа синтаксиса соответствующей обработки
css-loader: разборcssОператоры @import и url в файлах, обработкаcss-modules и вернуть результат в виде js-модуля.
postcss-loader: Преобразование css3 в более низкую версию, совместимую с браузером, и совместимость с будущими версиями написания css, загрузка соответствующего плагина.
autoprefixer: анализировать файлы CSS и добавлять префиксы браузера к содержимому CSS.
postcss: инструмент для использования плагинов для преобразования CSS.
less-loader: БудуlessКод переводится во что-то, что браузер может распознать.CSSкод
style-resources-loader: импортировать некоторые общие переменные файла стиля препроцессора css

npm install --save-dev vue-style-loader css-loader postcss-loader autoprefixer postcss less-loader style-resources-loader

конфигурация модуля

{
        test: /\.less$/,
        use: [
          'vue-style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 3
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              indent: 'postcss',
              plugins: (loader) => [
                require('autoprefixer')() // 添加前缀
              ],
              sourceMap: false
            }
          },
          {
            loader: 'less-loader',
            options: {
              javascriptEnabled: true,
              sourceMap: true
            }
          },
          {
            loader: 'style-resources-loader',
            options: {
              patterns: [
                path.resolve(__dirname, '../src/assets/css/variables/*.less'),
              ],
              injector: (source, resources) => {
                const combineAll = type => resources
                  .filter(({ file }) => file.includes(type))
                  .map(({ content }) => content)
                  .join('')

                return combineAll('variables') + combineAll('mixins') + source
              }
            }
          }
        ],
        exclude: /node_modules/
      },

npm run buildПроверка результата после упаковки image.png

less

style-resources-loader: избегайте повторения @import в каждом файле стилей и используйте переменные и общие стили непосредственно в каждом файле css.
На основе конфигурации css добавьте в конце style-resources-loader, чтобы вам больше не приходилось вручную вводить переменные css

{
        loader: 'style-resources-loader',
        options: {
          patterns: [
            path.resolve(__dirname, '../src/assets/css/variables/*.less')
          ],
          injector: (source, resources) => {
            const combineAll = type => resources
              .filter(({ file }) => file.includes(type))
              .map(({ content }) => content)
              .join('')

            return combineAll('variables') + combineAll('mixins') + source
          }
}

npm run buildПроверка результата после упаковки

image.png MiniCssExtractPlugin: извлекайте стили CSS в JS и импортируйте их извне со ссылкой, чтобы уменьшить размер файлов JS.

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

{
    plugins: [
        new MiniCssExtractPlugin({
          filename: '[name].[contenthash].css',
          chunkFilename: '[id].[contenthash].css',
          ignoreOrder: true
        }),
    ]
}

поставить вышеvue-style-loaderзаменитьMiniCssExtractPlugin.loader

npm run buildПроверка результата после упаковки image.png

изображение&svg&аудио&шрифт

svg-sprite-loader: Анализировать код js в ast, что удобно каждому плагину для анализа синтаксиса соответствующей обработки
url-loader: разборcssОператоры @import и url в файлах, обработкаcss-modules и вернуть результат в виде js-модуля.

npm install --save-dev svg-sprite-loader url-loader
 {
        test: /\.svg$/,
        loader: 'svg-sprite-loader',
        include: [path.join(__dirname, '..', 'src/assets/icon')],
        options: {
          symbolId: '[name]',
          name: path.posix.join('static', 'img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(png|jpe?g|gif)(\?.*)?$/,
        loader: 'url-loader',
        exclude: /node_modules/,
        options: {
          limit: 10000,
          name: path.posix.join('static', 'img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        exclude: /node_modules/,
        options: {
          limit: 10000,
          name: path.posix.join('static', 'media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff|woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: path.posix.join('static', 'fonts/[name].[hash:7].[ext]')
        }
      }

Публичный разделwebpack.common.jsоптимизация

1. externals исключает упаковку внешних зависимостей в пакеты

externals: {
  'vue': 'Vue',
}

npm run buildПроверка результата после упаковки: После настройки внешних параметров пакет vue.js не может быть найден в dist. На картинке ниже скриншот до настройкиimage.png

2. разрешение сужает диапазон поиска и снижает скорость поиска

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': path.join(__dirname, '..', 'src'),
      '@services': path.join(__dirname, '..', 'src/api/services.js'),
      '@productsManagement': path.join(__dirname, '..', 'src/modules/productsManagement')
    }
  },

3. кеш-загрузчик

cache-loader: добавить cache-loader перед некоторыми загрузчиками с высокой производительностью, чтобы кешировать результаты на диск, о чем написано здесьvue-loaderспереди

 {
    test: /\.vue$/,
    use: [
      {
        loader: 'cache-loader'
      },
      {
        loader: 'vue-loader'
      }
    ]
  },

npm run buildПроверка результата после упаковки: вы можете увидеть кешированные файлы в .cache под node_modules
image.png

3. plugins

  1. Подстановка переменной DefinePlugin
  2. Отображение прогресса упаковки WebpackBar
  3. FriendlyErrorsWebpackPlugin настроить журнал вывода терминала
  4. HtmlWebpackPlugin динамически генерирует html
  5. LodashModuleReplacementPlugin вводится по запросу
  6. Горячая перезагрузка VueLoaderPlugin
  7. HardSourceWebpackPlugin кэширует внутренние модули webpack
  8. многопоточная упаковка thread-loader
const WebpackBar = require('webpackbar')
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')

const argv = require('yargs-parser')(process.argv.slice(-3))
const mode = argv.mode || 'development'
const isDev = mode === 'development'
const jsWorkerPool = {
  poolTimeout: 2000
}


plugins: [
    new webpack.DefinePlugin({
      'process.env': JSON.stringify(mode),
      'process.env.BUILD_ENV': JSON.stringify(mode)
    }),
    new WebpackBar({
      name: isDev ? 'development' : 'production',
      color: isDev ? '#00953a' : '#f2a900'
    }),
    new FriendlyErrorsWebpackPlugin(),
    new LodashModuleReplacementPlugin(),
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      }
    }),
    new HardSourceWebpackPlugin({}),
],

HardSourceWebpackPlugin: предоставить промежуточный кеш для модуля, путь хранения кеша по умолчанию:node_modules/.cache/hard-source, первое время сборки сильно не меняется, а вот второе время начинается, время сборки можно сэкономить примерно на 80%

npm run buildПосле упаковки результат проверки HardSourceWebpackPlugin image.png

LodashModuleReplacementPlugin: этот плагин удалит функции lodash, которые вы не используете.npm run buildПосле упаковки проверяется результат LodashModuleReplacementPlugin. image.png

thread-loader: поместите этот загрузчик перед другими загрузчиками, а загрузчик, размещенный после этого загрузчика, будет работать в отдельном пуле рабочих процессов для ускорения упаковки. Здесь нет эксперимента, потому чтоthread-loaderПодходит для использования на трудоемких загрузчиках, иначе будет тормозить скорость.

4. optimization splitChunks& runtimeChunk(manifest)

splitChunks: Извлеките повторно вставленные файлы и сгенерируйте один или несколько файлов отдельно, чтобы избежать повторной упаковки файлов в несколько записей.
script-ext-html-webpack-plugin: БудуruntimeChunkВстроить в наш index.html
runtimeChunk. , что означает, что app.js изменится каждый раз, и кэш будет недействительным.

const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')

output: {
      path: path.resolve(__dirname, '../dist'),
      filename: '[name].[chunkhash].js',
      chunkFilename: '[name].[chunkhash].js',
      publicPath: '/'
},
plugins:[
    new ScriptExtHtmlWebpackPlugin({
      inline: /runtime\..*\.js$/
    }),
],
optimization: {
    runtimeChunk: true, // 构建出runtime~xx文件
    splitChunks: {
      name: true, // 自动处理文件名
      chunks: 'all',
      automaticNameDelimiter: '-',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: 10,
          name: 'vendors',
          chunks: 'initial'
        },
        commons: {
          name: 'commons',
          minChunks: 2,
          priority: 5,
          test: path.join(__dirname, '..', 'src/components'),
          reuseExistingChunk: true
        }
      }
    }
  }

Сначала создайте под srca.js、b.jsфайл, вmain.jsпройти черездинамическая нагрузка import()импорт,webpackChunkNameИмя пакета после импорта по требованию.npm run buildПосле упаковки результат runtimeChunk проверяется image.png image.png

npm run buildПосле упаковки проверяется результат splitChunks image.png

npm run buildПосле упаковки результат проверки script-ext-html-webpack-plugin image.png

5. Журнал выходных данных терминала конфигурации пакета статистики

stats: back-end скрипт упаковки разворачивается через докер, поэтому нужно настроить webpack на вывод информации, иначе информация будет черно-белой, и читать лог будет сложнее

stats: {
    colors: true,
    modules: false,
    children: false,
    chunks: false,
    chunkModules: false
  }

Оптимизация среды разработки

1. режим отладки devtool

существуетwebpack.common.jsВнутренняя конфигурация

const merge = require('webpack-merge')
const argv = require('yargs-parser')(process.argv.slice(-3))
const mode = argv.mode || 'development'
const mergeConfig = require(`./webpack.${mode}.js`)
const common = merge(commonConfig, mergeConfig)
module.exports = common
devtool: 'cheap-module-eval-source-map',

2. devServer & HotModuleReplacementPlugin

Обычно это так, поэтому я не буду вдаваться в подробности.

plugins:[ 
    new webpack.HotModuleReplacementPlugin()
],
devServer: {
    historyApiFallback: true,
    overlay: {
      errors: true
    },
    // 通知文件更改
    watchOptions: {
      poll: true
    },
    open: false,
    hot: true,
    proxy: {
      '/api': {
        target: 'http://localhost:10080/',
        changeOrigin: true,
        pathRewrite: {
          '^/api': '/api'
        }
      }
    },
    host: '0.0.0.0',
    port: 8000
},

Оптимизация производственной среды

todo: подумайте о том, что делает каждый плагинzhuanlan.zhihu.com/p/102632472

1. plugins

CleanWebpackPlugin: удалить расстояние
OptimizeCssAssetsPlugin: Плагин сжатия оптимизации css
cssnano: Один PostCSSПлагины, которые можно добавить в процесс сборки, чтобы конечный рабочий файл таблицы стилей CSS был как можно меньше.CompressionPlugin: Сжать для создания gzip

const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const CompressionPlugin = require('compression-webpack-plugin')

plugins: [
    new CleanWebpackPlugin(),
    new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.less$/g,
      cssProcessor: require('cssnano'),
      cssProcessorPluginOptions: {
        preset: ['default', {
          discardComments: { removeAll: true },
          normalizeUnicode: false, // 建议false,否则在使用unicode-range的时候会产生乱码
          safe: true // 避免 cssnano 重新计算 z-index
        }]
      },
      canPrint: true
    }),
    new CompressionPlugin({
      algorithm: 'gzip', // 'brotliCompress'
      test: /\.js$|\.html$|\.css/, // + $|\.svg$|\.png$|\.jpg
      threshold: 10240, // 对超过10k的数据压缩
      deleteOriginalAssets: false // 不删除原文件
    })
  ],
  optimization: {
    moduleIds: 'size',
    minimizer: [
      // 这样配置会存在只有css压缩的问题,这时webpack4原本自己配置好的js压缩会无效 ,需要重新配置UglifyJsPlugin(用于压缩js,webpack4内置了)一下
      // https://www.jianshu.com/p/dd9afa5c4d0f
      new OptimizeCssAssetsPlugin({})
    ]
  },

Внутри конфигурации ngix бэкэнд-проекта

gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 5;
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;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;

npm run buildПосле упаковки,OptimizeCssAssetsPluginПроверка результатовimage.png npm run buildПосле упаковки,CompressionPluginПроверка результатовimage.png image.png

2. optimization

  1. Moduleids постоянный кэшКак увидеть эффект чанка после упаковки

optimization.moduleIds: 'size'

image.png 2. UglifyJsPlugin

 minimizer: [
  new UglifyJsPlugin({
    exclude: /\.min\.js$/,
    parallel: os.cpus().length,
    cache: true,
    sourceMap: true,
    uglifyOptions: {
      compress: {
        warnings: false,
        drop_console: true,
        collapse_vars: true,
        reduce_vars: true
      },
      output: {
        beautify: false,
        comments: false
      }
    }
  })
]

image.png

Динамическая загрузка оптимизации проекта

Его можно использовать для более крупных компонентов в проекте.es6的 import()динамически загружать, добавлятьwebpackChunkNameВолшебные заметки.

  1. Всплывающие окна, такие как модальные окна и окна рисования, которые обычно не используются, могут быть асинхронно лениво загружены для этих компонентов и удалены из кода, загруженного на первом экране.
  2. Отложенная загрузка маршрута
{
  path: '/productsManagement/allProducts',
  name: 'AllProducts',
  component: () => import(
    /* webpackChunkName: `AllProducts` */
    /* webpackMode: "lazy" */
    '@productsManagement/allProducts/DyProductList'),
  meta: {
    keepAlive: true,
    requiresAuth: true
  }
},

Сравнение результатов

Скорость упаковки

До оптимизации время первой упаковки в производственной среде: 49038 мс.image.pngДо оптимизации второе время упаковки производственной среды: 70113 мс.image.pngПосле оптимизации время первой упаковки в рабочей среде: 47663 мс.image.pngПосле оптимизации второе время упаковки производственной среды: 13738 мс,на 70% быстрее image.png

Отображение размера ресурса после упаковки

image.pngЧтобы упорядочить файлы, выполните следующие действия: После подпакета упакуйте рабочий пакет без gzip и используйте gzip для загрузки небольших пакетов.image.png

Управление статическими ресурсами

icon

Я написал компонент иконкиvue-midou-icon. Этот компонент поддерживает стыковку платформы iconfont, и нет необходимости загружать иконку вручную. Он используется следующим образом:

// 注册
import MdUi from 'vue-midou-icon'
// 在main.js内导入
import "vue-midou-icon/lib/midou.css" 

const IconFont = MdUi.createFromIconfontCN({
  scriptUrl:[
    'your-iconfont-symbbol-url'
  ],
  // name可以不写 默认为 md-icon
  name: 'your-iconfont-component-name',
})
Vue.use(IconFont)


//组建使用
<your-iconfont-component-name type="iconType" class="className">
</your-iconfont-component-name>

images

  1. Изображения должны быть сжаты,сжатый адрес. Вы можете сжать несколько раз в соответствии с фактическим размером изображения.
  2. когда картинка маленькая. можно рассматривать локально. Упаковка в конфигурации webpack
  3. Если картинка представляет собой динамическую картинку в формате gif. Вы можете разрешить пользовательскому интерфейсу захватывать кадр за кадром перед предварительной загрузкой изображения. Как сделать предварительную загрузку можно обратиться кПредварительная загрузка изображения страницы и стратегия ленивой загрузки
  4. Изображения длинного списка используют изображение element-ui для поддержки ленивой загрузки.

<el-image v-for="url in urls" :key="url" :src="url" lazy></el-image>

fonts

В нашем проекте есть онлайн-редактирование изображений, поэтому нам нужно загрузить много шрифтов пользовательского интерфейса. Каждый пакет шрифтов имеет 17M до конвертации. Преобразование otf в woff путем сжатия и преобразования шрифтов. Становится 5кб, но шрифт будет немного изменен.Нажмите, чтобы ввести адрес сжатия шрифта

css

  1. спецификация переменной css, использованиеstyle-resources-loaderглобальная инъекция
  2. Общедоступный css сортируется отдельно, и вводится унифицированная запись
  3. Бизнес CSS и формирование единой папки

Оптимизация кода

Организация каталога и модульное деление

Общедоступные компоненты исходной структуры каталогов не отделены от бизнес-компонентов страницы, поэтому компонентов становится все больше и больше, и существует явление, когда компоненты в компонентах загружаются напрямую по маршруту. Структура каталогов перепутана. Не существует концепции модульного деления.image.png

Извлечь общедоступную логику из createLoading, modelExtengs, listModel, baseModel

  1. modelExtenddva-model-extend категории dva, щелкните имя, чтобы просмотреть код
  2. createBaseModelФильтрация и инкапсуляция запросов списка запросов, щелкните имя, чтобы просмотреть код
  3. createLoadingPluginЗагрузка промежуточного программного обеспечения действия категории два, щелкните имя, чтобы просмотреть код

Ниже приведен код, использующий демонстрацию

существуетstore.jsрегистрация в

import Vue from 'vue'
import Vuex from 'vuex'
import createLoadingPlugin from './plugins/createLoadingPlugin'
import {setBaseModelConfig} from '@commonModels/createBaseModel.js'
import productManagement from './modules/productManagement'
import customerSetting from './modules/customerSetting'

setBaseModelConfig({
  // 列表获取
  getList: (response) => {
    let tableData
    tableData = response.items
    return {
      tableData,
      total: response.total
    }
  },
  // 参数格式化 
  formatParmas: (parmas) => {
    // 合并分页和筛选的数据
    return {
      ...parmas.pagination,
      ...parmas.filters
    }
  },
  // 错误警告
  handleError: (err, self) => {
    self._vm.$message({
      message: `${err}`,
      type: 'error'
    })
  },
  // 分页配置
  pagination: {
    page_size: 10,
    page_index: 1
  }
})

Vue.use(Vuex)
const modules = {
  ...productManagement,
  ...customerSetting
}

export default new Vuex.Store({
  modules,
  plugins: [createLoadingPlugin({Vue})]
})

существуетvuexмонтировать в файл

import createBaseModel from '@commonModels/createBaseModel.js'
import modelExtend from '@commonModels/modelExtend.js'
import services from '@services'

const model = modelExtend(
  createBaseModel({
    fetch: services.userCapturePage
  }),
  {
    namespaced: true,
    state: () => ({
    }),
    actions: {
      async fetch ({commit, state, dispatch}, payload) {
        await dispatch('query', { ...payload })
      }
    },
    getters: {

    }
  })
export default model

Вызовы в файлах **.vue**

<!-- 额度消耗记录-->
<template>
    <el-table
      :data="tableData"
      v-loading="loading"
      style="width: 100%">
      <el-table-empty slot="empty" />
      <el-table-column
        prop="create_time"
        label="复制时间"
        width="180">
      </el-table-column>
      <el-table-column
        prop="url"
        label="复制链接">
      </el-table-column>
    </el-table>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="pagination.page_index"
      class="pt-20 right mr-20"
      :page-size="pagination.page_size"
      :page-sizes="[10, 20, 50, 100]"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
    >
    </el-pagination>
</template>

<script>
import { mapState, mapActions } from 'vuex'

export default {
  name: 'ConsumptionRecord',
  data () {
    return {
    }
  },
  created(){
    this.fetch({
        pagination: {
          page_size: 10,
          page_index: 1
        }
      })
  },
  computed: {
    // customerSetting/paidRecharge/consumptionRecord 
    // 组建层级路径 在store内也保持一致 利于后期代码维护和模块分离
    ...mapState('customerSetting/paidRecharge/consumptionRecord', [
      'tableData',
      'total',
      'pagination',
      'filters'
    ]),
    ...mapState({
      loading: state => state['@@loading'].effects['customerSetting/paidRecharge/consumptionRecord/fetch']
    })
  },
  methods: {
    ...mapActions('customerSetting/paidRecharge/consumptionRecord', [
      'handleCurrentChange',
      'handleSizeChange',
      'setFilter',
      'fetch'
    ])
  }
}
</script>

Автоматическая регистрация с помощью require.context

const requireDirectives = require.context(
  '@/dirname',
  false,
  /([\w\W]*)\.(vue|js)$/
)

export const registerDirectives = () =>
  requireDirectives.keys().forEach(fileName => {
    const directiveConfig = requireDirectives(fileName)
    const directiveName = fileName.split('/').pop().replace(/\.\w+$/, '')
    Vue.directive(
      directiveName,
      directiveConfig.default || directiveConfig
    )
  })

попросить лайк

Пока разрабатываю и делаю, лично я чувствую, что есть еще много несовершенств. Я надеюсь, что вы можете дать мне несколько советов, когда увидите его, большое спасибо. . Если вы думаете, что это хорошо, пожалуйста, как это, спасибо, ребята! ! ! ! 💗