Построение с нуля до оптимизации скаффолда, похожего на vue-cli

внешний интерфейс Webpack
Построение с нуля до оптимизации скаффолда, похожего на vue-cli

предисловие

Предположительно, большинство людей будут использовать его напрямую при разработке проектов SPA, таких как vue.vue-cliВ ожидании развития строительных лесов, во-первых, это удобно, чтобы сэкономить много усилий по настройке, а во-вторых, это то, чтоvue-cliВ конце концов, какова доказанная зрелая, возникающие проблемы могут найти соответствующие решения в Интернете.

Однако, если мы хотим лучше понять конфигурацию скаффолдинга, его конструкцию и механизм упаковки, нам необходимо с нуля настроить проект, аналогичный vue-cli. Здесь я сделал следующую простую конфигурацию, пожалуйста, критикуйте и исправьте меня, и искренне надеюсь, что я смогу получить руководство от большого человека, чтобы решить проблему в конце статьи.Tree ShakingПроблемы, приводящие к отсутствию css в упаковке.

Эта статья в основном включает следующие конфигурации:

  • Различать переменные среды и объединять конфигурацию
  • webpack-dev-serverлокальный сервер
  • HtmlWebpackPluginсгенерировать html
  • CleanWebpackPluginочистить папки
  • loaderа такжеbabelнастроить
  • HotModuleReplacementPluginГорячее обновление
  • postcss-loaderдобавить префикс css
  • vue SPAВведение и анализ
  • vue-routerустановка и использование
  • mini-css-extract-pluginОтдельные CSS
  • purifycss-webpack purify-cssУстранить избыточные CSS
  • optimize-css-assets-webpack-pluginсжатый css
  • terser-webpack-pluginсжатый js
  • splitChunksИзвлечь общедоступный код
  • image-webpack-loaderСжатие изображения
  • gZipУскорить оптимизацию

Исходный код проекта:GitHub.com/Майкл-Ли Чжиган...

Если вы не знаете базовую конфигурацию маленького партнера webpack, просмотрите следующую статью.
Создайте проект веб-пакета с нуля
Создайте мобильную среду vue-cli4+webpack (из коробки)

Создайте структуру проекта веб-пакета

Создайте структуру проекта

  1. Создайтеwebpack-vue-cliпапка,npm-init-yИнициализировать проект

  2. Установите зависимости, связанные с веб-пакетом

npm i webpack webpack-cli webpack-dev-server webpack-merge --save-dev

еслиwebpackа такжеwebpack-cliЕсли нет глобальной установки, вы должны сначала установить ее глобально

  1. Создать папку проекта
├── src   // webpack配置文件
    |——main.js  // 入口文件
├── static   // 项目打包路径
├── index.html   // 模板html
├── webpack.base.js   // 打包基本配置
├── webpack.dev.js   // 本地环境配置
├── webpack.prod.js   // 生产环境配置

index.htmlа такжеmain.jsНечего сказать о коде, перейдите непосредственно по ссылке конфигурации веб-пакета.

Различайте окружающую среду

Чтобы лучше оптимизировать упаковку, мы разделяем конфигурацию WebPack в разработку окружающей среды и производственной среде.

  • общедоступный файл конфигурации webpack.base.js
  • Файл конфигурации для среды разработки webpack.dev.js
  • Файл конфигурации webpack.prod.js для рабочей среды

существуетwebpack.dev.jsа такжеwebpack.prod.js, мы можем использоватьwebpack-mergeОбъединить конфигурацию.

Затем мы определяем команды упаковки для разных сред в package.json.

"scripts": {
  "dev": "webpack-dev-server  --config webpack.dev.js --mode development",
  "build": "webpack --config webpack.prod.js"
}

общедоступная конфигурация

Давайте сначала посмотримwebpack.base.jsобщедоступная конфигурация, определите файл входа и файл выхода

module.exports = {
  entry: {
    index: path.join(__dirname, '/src/main.js'),
  },
  output: {
    path: path.join(__dirname, '/dist'), //打包后的文件存放的地方
    filename: 'js/[name].[hash].js', // 每次保存 hash 都变化
  },
}

webpack-dev-server

webpack предоставляет дополнительный локальный сервер разработки на основеnode.jsпостроить, так что вwebpack.dev.jsнастроить

const merge = require('webpack-merge') // 引入webpack-merge功能模块
const common = require('./webpack.base.js') // 引入webpack.common.js

module.exports = merge(common, {
  // 将webpack.common.js合并到当前文件
  devServer: {
    contentBase: './dist', // 本地服务器所加载文件的目录
    port: '8899', // 设置端口号为8088
    inline: true, // 文件修改后实时刷新
    historyApiFallback: true, //不跳转
    hot: true, // 热更新
  },
  mode: 'development', // 设置mode
})

HtmlWebpackPlugin

HtmlWebpackPluginУпрощает создание HTML-файлов, может автоматически создавать для вас упакованные html-файлы после упаковки в соответствии с html-шаблоном. Это полезно для файлов, которые содержат хэш в имени файла, который меняется каждый раз при компиляции.bundle.

plugins: [
  new HtmlWebpackPlugin({
    template: path.join(__dirname, '/index.html'), // new一个这个插件的实例,并传入相关的参数
  }),
]

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

конфигурация загрузчика

loaderможет позволитьwebpackспособен справиться с темиjavaScriptдокумент(webpackтолько понятьjavaScript).loaderВы можете преобразовать все типы файлов в действительные модули, которые может обрабатывать веб-пакет, а затем вы можете воспользоваться возможностями упаковки веб-пакета и обработать их.

дляloaderНаучно-популярная и конфигурация .jsи файлloader.

module: {
  rules: [
    {
      test: /\.css$/, // 正则匹配以.css结尾的文件
      use: ['style-loader', 'css-loader'],
    },
    {
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader'],
    },
    {
      test: /\.js$/,
      loader: 'babel-loader',
      include: [resolve('src')],
    },
    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('img/[name].[hash:7].[ext]'),
      },
    },
  ]
}

Для более удобной настройки и оптимизацииbabel-loader, мы можем извлечь его и создать новый в корневом каталоге.babelrcдокумент

{
  "presets": ["env"]
}

CleanWebpackPlugin

Очищайте папку /dist перед каждой сборкой, чтобы создавать последние упакованные файлы, которые используются в настоящее время.CleanWebpackPluginплагин тоже.

plugins: [
  new HtmlWebpackPlugin({
    template: path.join(__dirname, '/index.html'), // new一个这个插件的实例,并传入相关的参数
  }),
  new CleanWebpackPlugin(), // 所要清理的文件夹名称
]

HotModuleReplacementPlugin

HotModuleReplacementPlugin(HMR) — очень практичный плагин, который может автоматически обновлять эффект предварительного просмотра после того, как мы изменим код и используем его в среде разработки.

  1. devServerНабор элементов конфигурацииhot: true

  2. HotModuleReplacementPluginОн поставляется с модулем webpack, поэтому после введения webpack вpluginsЕго можно использовать непосредственно в элементе конфигурации.

plugins: [
  new webpack.HotModuleReplacementPlugin(), // 热更新插件
]

добавить префикс css

Обычно, когда мы пишем css, некоторым свойствам нужно добавлять префикс вручную, например-webkit-border-radius: 10px;, в вебпаке мы можем позволить ему автоматически добавлять

  1. Установить зависимости
npm i postcss-loader autoprefixer -D
  1. Создайте новый проект в корневом каталоге проектаpostcss.config.jsдокумент
module.exports = {
  plugins: [
    require('autoprefixer'), // 引用autoprefixer模块
  ],
}
  1. Изменить загрузчик стилей
rules: [
  {
    test: /\.css$/, // 正则匹配以.css结尾的文件
    use: ['style-loader', 'css-loader', 'postcss-loader'],
  },
  {
    test: /\.less$/,
    use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'],
  },
]

На данный момент проект веб-пакета в основном построен, далее представлены ссылка на vue и оптимизация проекта.

Создайте шаблон vue SPA

vue SPA

1. Создайтеvue-cliПодмости, прежде всего, нарисуем черпак по тыкве, вmain.jsнаписать код

import Vue from 'vue'
import App from './App.vue'
new Vue({
  el: '#app',
  render: (h) => h(App),
})

2. Затем создайте новый в папке srcAPP.vue

<div id="app">SPA项目</div>

3. Установите связанные зависимости

мы здесьnpm run devПопробуйте и получите ошибку. Поскольку мы не устанавливали соответствующие зависимости, давайте установим зависимости

npm install vue vue-loader vue-template-compiler -D
  • vue: исходный код vue
  • vue-loader: анализ файлов .vue
  • vue-template-compiler: скомпилировать vue

4, веб-пакет конфигурации vue-loader

const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
    ],
  },
  plugins: [new VueLoaderPlugin()],
}

vue-router

1. Установите зависимости

npm install vue-router -D

2. Создайте новый маршрутизатор/индекс в папке src.

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const router = new Router({
  routes: [
    {
      path: '/',
      component: () => import('../views/Home.vue'),
    },
    {
      path: '/admin',
      component: () => import('../views/admin.vue'),
    },
  ],
})

export default router

3. Ссылка в main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

new Vue({
  el: '#app',
  router,
  render: (h) => h(App),
})

Просто так, аvue-cliСтроительные леса установлены, и вы можете с радостью писать.vueфайл для разработки SPA.

webpack оптимизирует упаковку

Отдельные CSS

Хотя идея webpack заключается в том, чтобы упаковать все css и js в один файл, если мы хотим разделить css, здесь мы используемmini-css-extract-plugin. Еще один плагин контрастаextract-text-webpack-plugin, имеет следующие преимущества:

  • Асинхронная загрузка
  • Нет повторной компиляции, лучшая производительность
  • проще в использовании
  • Только для CSS

ноmini-css-extract-pluginне поддерживаетсяHMR, поэтому мы можем использовать его только в производстве.

1. Установите зависимости

npm install mini-css-extract-plugin -D

2. Вwebpack.prod.jsнастроитьloaderа такжеplugin

module: {
  rules: [
    {
      test: /\.(le|c)ss$/,
      use: [
        {
          loader: MiniCssExtractPlugin.loader,
          options: {
            publicPath: '../'
          },
        },
        'css-loader',
        'postcss-loader',
        'less-loader',
      ]
    }
  ]
},
plugins: [
  new MiniCssExtractPlugin({
    filename: "css/[name].[contenthash:8].css",
    chunkFilename: 'css/[id].[contenthash:8].css'
  })
]

Разделение css требует помещенияcss loaderсерединаstyle-loaderзаменитьMiniCssExtractPlugin

Удалите избыточный CSS

Иногда мы пишем слишком много или дублируем CSS, что приводит к избыточному коду, который мы хотим удалить в рабочей среде.

1. Установите зависимости

npm i purifycss-webpack purify-css glob -D

2. Конфигурация webpack.prod.js

const path = require('path')
const PurifyCssWebpack = require('purifycss-webpack') // 引入PurifyCssWebpack插件
const glob = require('glob') // 引入glob模块,用于扫描全部html文件中所引用的css

module.exports = merge(common, {
  plugins: [
    new PurifyCssWebpack({
      paths: glob.sync(path.join(__dirname, 'src/*.html')),
    }),
  ],
})

сжатый css

Мы хотим уменьшить объем упакованного css, который можно использоватьoptimize-css-assets-webpack-plugin. 1. Установите зависимости

npm install optimize-css-assets-webpack-plugin -D

2. Конфигурация webpack.prod.js

const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin") // 压缩css代码

optimization: {
  minimizer: [
    // 压缩css
    new OptimizeCSSAssetsPlugin({})
  ]

сжатый js

Webpack4.0 по умолчанию используетterser-webpack-pluginЭтот плагин сжатия, ранее использовавшийсяuglifyjs-webpack-pluginРазница между ними заключается в том, что последнее сжатие ES6 не очень хорошее, и мы можем открытьparallel

1. Установите зависимости

npm install terser-webpack-plugin -D

2. Конфигурация webpack.prod.js

const TerserPlugin = require('terser-webpack-plugin') // 压缩js代码

optimization: {
  minimizer: [
    new TerserPlugin({
      parallel: 4, // 开启几个进程来处理压缩,默认是 os.cpus().length - 1
      cache: true, // 是否缓存
      sourceMap: false,
    }),
    // 压缩css
    new OptimizeCSSAssetsPlugin({}),
  ]
}

Извлечь общедоступный код

При упаковке с помощью webpack для некоторых сторонних библиотек, которые не обновляются часто, таких как некоторые вещи в корзине семейства vue, мы надеемся, что они будут отделены от нашего собственного кода. использование веб-пакета4splitChunksспособ настройки.

optimization: {
  // 分离chunks
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendor: {
        name: "vendor",
        test: /[\\/]node_modules[\\/]/,
        priority: 10,
        chunks: "initial" // 只打包初始时依赖的第三方
      },
    }
  }
}

Сжатие изображения

Некоторые картинки в проекте слишком велики, чтобы повлиять на загрузку, мы используемimage-webpack-loaderСжатие.

1. Установите зависимости

npm install image-webpack-loader -D

2. Настроить загрузчик

{
  test: /\.(png|jpg|svg|gif)$/,
  use: [
    {
      loader: 'url-loader',
      options: {
        esModule: false,
        limit: 1000,  // 限制只有小于1kb的图片才转为base64
        outputPath: 'images', // 设置打包后图片存放的文件夹名称
        name: '[name][hash:8].[ext]'
      }
    },
    {
      loader: 'image-webpack-loader',
      options: {
        // 压缩 jpeg 的配置
        mozjpeg: {
          progressive: true,
          quality: 65
        },
        // 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
        optipng: {
          enabled: false,
        },
        // // 使用 imagemin-pngquant 压缩 png
        pngquant: {
          quality: [0.65, 0.90],
          speed: 4
        },
        // 压缩 gif 的配置
        gifsicle: {
          interlaced: false,
        },
        // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
        webp: {
          quality: 75
        }
      }
    }
  ]
}

ускоренная оптимизация gZip

Все современные браузеры поддерживаютgzipсжатие, включитьgzipСжатие может значительно уменьшить размер ресурсов передачи, тем самым сокращая время загрузки ресурсов, уменьшая время первого белого экрана и улучшая взаимодействие с пользователем.

gzip лучше всего работает с текстовыми форматами файлов (например, CSS, JavaScript и HTML), часто достигая 70–90% сжатия при сжатии больших файлов, а также для уже сжатых ресурсов (например, изображений). очень плохой.

const CompressionPlugin = require('compression-webpack-plugin')
configureWebpack: (config) => {
  if (process.env.NODE_ENV === 'production') {
    config.plugins.push(
      new CompressionPlugin({
        // gzip压缩配置
        test: /\.js$|\.html$|\.css/, // 匹配文件名
        threshold: 10240, // 对超过10kb的数据进行压缩
        deleteOriginalAssets: false, // 是否删除原文件
      })
    )
  }
}

tree-shaking (помогите, производственная среда не может быть упакована для создания стилей)

Сборка проекта описанным выше способом всегда была гладкой в ​​среде разработки, но после выполненияnpm run build, откройте страницу и обнаружите, что все стили отсутствуют. Открытьdist/cssпапку, нашел три файла css, толькоindex.cssЕсть некоторые файлы (main.js вводит начальные стили, но они неполные), а два других css файла пустые, то есть все стили в .vue отсутствуют.

Глядя на ресурсы, изначально предполагается, что по умолчанию используется webpack4.tree-shaking, БудуНа уровне модуля упакованный код содержит только те модули, на которые есть ссылки и которые выполняются, а модули, на которые нет ссылок или которые не выполняются, удаляются для уменьшения размера пакета.. Но я следил за соответствующими ресурсами наpackage.jsonнастроенsideEffectsДа, но это все еще не работает, это действительно раздражает! ! !

"sideEffects": [
    "*.less",
    "*.css",
    "*.vue"
  ]

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

рекомендуемая статья