Интервьюер: Вы когда-нибудь писали загрузчики и отдельные модули при использовании веб-пакета?

опрос

предисловие


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

Обзор

  • Как загрузить свой загрузчик
  • Использование утилит-загрузчиков, утилит-схем
  • Напишите свой загрузчик
  • расширять

Как загрузить свой загрузчик

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

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

//webpack.config.js
const path = require("path");
module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                use: [
                    {
                        loader: path.resolve("loader.js"),
                        options: {
                            test: 'apple'
                        }
                    }
                ]
            }
        ]
    }
};

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

path.resolve('loader.js') возвращает путь

/Users/kev1nzh/Desktop/my/webpack/loader.js

Используйте один загрузчик
在使用一个loader的时候,loader会接收你正则匹配的资源文件(如上,所有js文件)的字符串。

loader通过代码转化模块后,最后返回传递出去。
Используйте несколько загрузчиков
  • При использовании нескольких загрузчиков передайте строку файла ресурсов в обратном порядке, начиная с последнего массива переданных загрузчиков.

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

  • Загрузчик посередине получает предыдущий загрузчик и после конвертации передает его следующему.

  • Наконец, первый загрузчик получает преобразование и передает все строки файлов ресурсов, обработанные загрузчиком.

{
     test: /\.css$/,
     use: [
         {
             loader: 'css-loader'
         },
         {
             loader: 'style-loader'
         },
     ]
}
//style-loader接收所有css的文件,转化完再传给css-loader,转化完后再怼出来。

Использование утилит-загрузчиков, утилит-схем

loader-utils, schema-utils — это библиотека инструментов загрузчика webpack, есть много удобных методов для вызова.

const { getOptions,stringifyRequest, parseQuery  } = require("loader-utils");
const validateOptions = require("schema-utils");
const schema = {
    type: "object",
    properties: {
        test: {
            type: "string"
        }
    }
};
module.exports = function(source) {
    //getOptions 用于在loader里获取传入的options,返回的是对象值。
    const options = getOptions(this);
    
    // stringifyRequest转换路径,避免require()或impot时使用的绝对路径
    stringifyRequest(this, "./test.js"); //   Result =>  "\"./test.js\""
    
    //parseQuery获取query参数的,这个很简单就不说啦
    parseQuery('?name=kev&age=14') // Result => {name: 'kev', age: '14'}
    
    //验证参数的类型是否正确。
    validateOptions(schema, options, "loader");
};

Напишите свой загрузчик

Наконец-то пришло время сеанса рукописного ввода! ! ! !

//webapck.config.js
const path = require("path");

module.exports = {
    entry: "./src",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "package.js"
    },
    mode: "production",
    module: {
        rules: [
            {
                test: /\.js$/,
                use: [
                    {
                        loader: path.resolve("loader.js"),
                        options: {
                            work: '996',
                            sick: 'ICU',
                        }
                    }
                ]
            }
        ]
    }
};

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

Первый шаг — проверить, соответствуют ли параметры типу.

Второй шаг — получить параметры, а затем заменить строку входящего файла ресурсов.

//loader.js
const { getOptions } = require("loader-utils");
const validateOptions = require("schema-utils");

const schema = {
    type: "object",
    properties: {
        work: {
            type: 'String'
        },
        sick: {
            type: 'String'
        }
    }
};

module.exports = function(source) {

    const options = getOptions(this);
    validateOptions(schema, options, 'loader');

    const  {work, sick} = options;
    source = source.replace(/\[work\]/g, work).replace(/\[sick\]/g, sick);

    return `export default ${JSON.stringify(source)}`;
};

Покажите js для конвертации.

// src/index.js
console.log('工作[work] 生病[sick] 加班不规范 亲人两行泪');

Наконец, в командной строке webpack! ! ! ! !


расширять

Как работает вебпак?
const index = require('./index');
const console = require('./console');

//index.js
const axios = require('./scripts/debounce.js'');
const moment = require('moment');
// do something
  1. WebPack будет разбирать все модули, и если модуль имеет зависимости от других файлов, он будет продолжать разбирать зависимые модули. пока файл не не имеет зависимостей.
  2. После синтаксического анализа webpack инкапсулирует все модули в функцию и помещает их в массив с именем modules.
  3. Передайте модули в самовыполняющуюся функцию, а самоисполняющаяся функция содержит объект InstallModules, и в этом объекте будут сохранены исполняемые модули кода.
  4. Наконец, загрузите функцию в самовыполняющуюся функцию (webpack__require), чтобы загрузить модуль.

отдельный код

// ./src/moment.js
const moment = require('moment');
console.log(moment().format('MMMM Do YYYY, h:mm:ss a'))

// ./index.js
const momentJs = require('./src/moment');
console.log(123);

Как указанный выше код, давайте упакуем его и попробуем.

Два файла имеют зависимости, поэтому после упаковки модуль момента будет упакован.

SplitChunksPlugin

Метод разделения кода из webpack4.x, предыдущего плагина CommonsChunkPlugin, был удален. Этот модуль работает «из коробки» и по умолчанию влияет только на блоки по требованию, так как изменение начального блока влияет на теги сценария, которые должен содержать файл HTML для запуска проекта.

webpack автоматически разбивает чанки на основе следующих условий:

  • Новые блоки или модули из этой папки node_modules могут быть общими
  • Новый блок будет больше 30 КБ (до min+gz)
  • Максимальное количество параллельных запросов при загрузке чанков по мере необходимости будет меньше или равно 5
  • Максимальное количество одновременных запросов при начальной загрузке страницы будет меньше или равно 3.
  • При попытке удовлетворить последние два условия предпочтительны более крупные куски.

Давайте посмотрим, как это делает код!

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'initial',   //选择哪些模块需要优化, 参数为 all、async、initial
      minSize: 30000,  // 要生成的块的最小数
      maxSize: 0,  //要生成的块的最大数
      minChunks: 2, // 分割前共享模块的最小块数
      maxAsyncRequests: 5, //按需加载时的最大并行请求数
      maxInitialRequests: 3, // 入口的最大并行请求数
      automaticNameDelimiter: '~',  //指定生成文件名当中的分隔符
      name: true, //拆分块的名称
      cacheGroups: { //缓存组
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};


Ну, что нужно сказать, закончилось.

Первая часть цикла интервью:Интервьюер: Вы знаете Callback Hell?

Вторая часть цикла интервью:Интервьюер: Есть ли разница между react и vue?

Третья часть цикла интервью:Интервьюер: Вы знаете, что такое es6?

Четвертая часть цикла интервью:Интервьюер: Вы знаете Webpack?

Если у вас есть какие-либо достижения или вопросы, пожалуйста, прокомментируйте ниже и поставьте лайк! Спасибо за просмотр здесь.