«Серия WebPack» - подробное объяснение конфигурации погрузчика

Webpack
«Серия WebPack» - подробное объяснение конфигурации погрузчика

1. Что такое загрузчик

A loader is just a JavaScript module that exports a function.

С точки зрения синтаксиса загрузчик — это обычный модуль Node.js, который для использования необходимо экспортировать в формате функции. При необходимости можно использовать все функциональные модули Node.js.

С функциональной точки зрения загрузчик воздействует на файл ресурсов в указанном формате в Webpack и преобразует его в вывод в определенном формате. Например: less-loader преобразует меньше файлов в выходной файл css.

Во-вторых, характеристики загрузчика

Единственная ответственность, загрузчик делает только одну вещь, просто потому, что ответственность более разовая, поэтому загрузчики имеют сильную композицию и хорошую конфигурируемость.

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

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

При изучении конфигурации загрузчика лучше всего построить простуюWebpack Demo,воплощать в жизньwebpackКоманда упакована, и вы можете проверить правильность конфигурации.

Конфигурация загрузчика в Webpack может быть написана различными способами, которые подробно описаны ниже.

Давайте сначала рассмотрим простую конфигурацию загрузчика.

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader','css-loader']
            },
        ],
    },
}

Загрузчик настраивается в Module.Rules, значением module.rules является правило создания модулей, а значением module.rules является массив, каждый из которых является правилом. Загрузчик используется для создания модуля, соответствующего WebPack. Затем WebPack упаковал эти модули для создания соответствующего JS-файла. Загрузчик выполняется перед пакетом.

Как показано на рисунке ниже, используетсяstyle-loaderа такжеcss-loaderМодули генерируются двумя загрузчиками.

Здесь каждое правило в module.rules называется Rule.Поговорим об условиях настройки правила и загрузчике для настройки правила.

1. Настройте условия правила

Rule.test

В простой конфигурации загрузчикаtest:/\.css$/, заключается в фильтрации имен, начинающихся с.cssПосле окончания файла, переданногоuserЗагрузчик в опциях с этим справляется.

ТакtestФункция опции заключается в фильтрации ресурсов, а квалифицированные ресурсы обрабатываются загрузчиком в этом правиле.

testЗначение может быть строкой, регулярным выражением, функцией, массивом.

  • Если значение представляет собой строку, это может быть абсолютный путь к каталогу, в котором находится ресурс, или абсолютный путь к ресурсу.
const path = require('path');
module.exports = {
    module: {
        rules: [
            {
                test: path.resolve(__dirname, 'src/css'),
                //test: path.resolve(__dirname, 'src/css/index.css'),
                use: ['style-loader','css-loader']
            },
        ],
    },
}
  • Когда значение является функцией, полученный параметр является абсолютным путем к ресурсу. Возвращает true, чтобы указать, что ресурс может быть переданuserЗагрузчик в опциях с этим справляется.
\project\03personal\05Webpack_demo\src\css\index.css
module.exports = {
    module: {
        rules: [
            {
                test: function (path) {
                    return path.indexOf('.css') > -1
                },
                use: ['style-loader','css-loader']
            },
        ],
    },
}
  • Когда значение представляет собой массив, каждый элемент массива может быть строкой, регулярным выражением или функцией. Если ресурс соответствует любому из условий в массиве, он может быть передан вuserЗагрузчик в опциях с этим справляется.
const path = require('path');
module.exports = {
    module: {
        rules: [
            {
                test: [/\.css$/,path.resolve(__dirname, 'src/css')]
                use: ['style-loader','css-loader']
            },
        ],
    },
}

Rule.include

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

const path = require('path');
module.exports = {
    module: {
        rules: [
            {
                include:/\.css$/,
                //include: path.resolve(__dirname, 'src/css'),
                //include: path.resolve(__dirname, 'src/css/index.css'),
                //include: [/\.css$/,path.resolve(__dirname, 'src/css')],
                //include:function (content) {
                    //return content.indexOf('src/css') > -1
                //},
                use: ['style-loader','css-loader']
            },
        ],
    },
}

Rule.exclude

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

const path = require('path');
module.exports = {
    module: {
        rules: [
            {
                exclude:/node_modules/,
                //exclude: path.resolve(__dirname, 'node_modules'),
                //exclude: [/node_modules/ , path.resolve(__dirname, 'node_modules')],
                //exclude:function (content) {
                    //return content.indexOf('node_modules') > -1
                //},
                use: ['style-loader','css-loader']
            },
        ],
    },
}

Rule.issuer

Использование такое же, как Rule.test, но обратите внимание на соответствиеПуть файла импортируемого ресурса,

Например, введение css/index.css в main.js.

const path = require('path');
module.exports = {
    module: {
        rules: [
            {
                issuer: /\main\.js$/,
                //issuer: path.resolve(__dirname, 'main.js'),
                //issuer: [/\main\.js$/ , path.resolve(__dirname, 'main.js')],
                //issuer:function (content) {
                    //return content.indexOf('main.js') > -1
                //},
                use: ['style-loader', 'css-loader']
            },
        ],
    },
}

Когда Rule.issuer и Rule.test, Rule.include, Rule.exclude используются одновременно, это также отношение «и».

Rule.resource

Этот параметр также может фильтровать ресурсы и разрешать загрузчику в этом правиле обрабатывать квалифицированные ресурсы.

но настроитьresourceПосле варианта,test,include,excludeопция не может быть использована.issuerопция не действует.

resourceОпции имеют следующие подопции

  • testПараметры, использование такое же, как Rule.test.
  • excludeПараметры, использование такое же, как Rule.exclude.
  • includeОпции, использование такое же, как Rule.include.
  • notОпция, значение представляет собой массив, каждый элемент массива может быть строкой, регулярным выражением, функциями, если ресурс соответствует любую из условий в массивепросто не могусдаватьuserЗагрузчик в опциях с этим справляется.
  • andОпция, значением является массив, каждый элемент массива может быть строкой, регулярным выражением, функцией,долженсоответствовать массивукаждое условиересурсталантсдаватьuserЗагрузчик в опциях с этим справляется.
  • orОпция, значением является массив, каждый элемент массива может быть строкой, регулярным выражением, функцией, до тех пор, пока ресурс удовлетворяет любому из условий в массивемогусдаватьuserЗагрузчик в опциях с этим справляется.
const path = require('path');
module.exports = {
    module: {
        rules: [
            {
                resource:{
                    test:/\.css$/,
                    include: path.resolve(__dirname, 'src/css'),
                    exclude: path.resolve(__dirname, 'node_modules'),
                },
                use: ['style-loader', 'css-loader']
            },
        ],
    },
}

Rule.resourceQuery

Соответствует части пути импорта ресурсов, которая начинается со знака вопроса. пример

import './ass/main.css?inline'

Rule.resourceQuery в приведенном выше коде должен соответствовать?inline,пример

const path = require('path');
module.exports = {
    module: {
        rules: [
            {
                resourceQuery:/inline/,
                // resourceQuery:function (content) {
                    //return content.indexOf('inline') > -1
                // },
                //resourceQuery:[/inline/],
                use: ['style-loader', 'css-loader']
            },
        ],
    },
}

Уведомление

  • Когда Rule.test, Rule.include, Rule.exclude, Rule.issuer и Rule.resourceQuery используются одновременно, это отношение "и". Все указанные выше условия конфигурации должны быть выполнены одновременно перед загрузчик в этом правиле может его обработать.
  • Когда Rule.issuer, Rule.resourceQuery и Rule.resource используются одновременно, это также связь «и». Все вышеперечисленные условия конфигурации должны быть выполнены одновременно, чтобы загрузчик в этом правиле мог выполнить обработку.

2. Настроить загрузчик правила Rule

Rule.use

Использование Rule.use было упомянуто выше. Это означает, какие загрузчики используются для обработки подходящих ресурсов.

use: ['style-loader']Фактическиuse: [ { loader: 'style-loader'} ]сокращение для .

также черезoptionsПроход в загрузчик можно понимать как опцию для загрузчика.

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1
                        }
                    },
                ]
            },
        ],
    },
}

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

  • compiler: Текущий компилятор веб-пакета (может быть неопределенным).
  • issuer: Абсолютный путь к файлу, в который импортируется ресурс для обработки.
  • realResource: Абсолютный путь обрабатываемого ресурса.
  • resource: абсолютный путь к обрабатываемому ресурсу, часто заменяется на realResource, только если имя ресурса переопределяется !=! в строке запроса.
  • resourceQuery: В абсолютном пути обрабатываемого ресурса? задняя часть.
module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: (info) =>{
                    console.log(info)
                    return [
                        'style-loader',
                        {
                            "loader": 'css-loader',
                        },
                    ]
                },
            },
        ],
    },
}

Информация о параметрах распечатывается, как показано ниже.

Rule.loader

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                loader: 'css-loader',
            },
        ],
    },
}

loader: 'css-loader'даuse: [ { loader: 'css-loader'} ]сокращение для .

Rule.oneOf

При совпадении правила используется только первое соответствующее правило.

Например, когда вы хотите обрабатывать файловые ресурсы CSS, one.css обрабатывается с помощью URL-Loader, two.css для использования File-Loader. Вы можете использовать Rule.oneof для настройки, использование такое же, как и для module.rules.

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                oneOf: [
                    {
                        resourceQuery: /one/, // one.css?one
                        //test: /one\.css/,
                        use: 'url-loader'
                    },
                    {
                        resourceQuery: /two/, // two.css?two
                        //test: /one\.css/,
                        use: 'file-loader'
                    }
                ]
            },
        ],
    },
}

В-четвертых, порядок выполнения загрузчика

Справа налево, снизу вверх. Другими словами, последняя запись выполняется первой, точно так же, как стек последним пришел, первым вышел.

rules: [
    {
        test: /\.less$/,
        use: ['style-loader','css-loader','less-loader']
    },
],

В приведенной выше конфигурации сначала выполняется less-loader, затем css-loader и, наконец, style-loader.

rules: [
    {
        test: /\.less$/,
        use:[
            {
                loader:'style-loader'
            },
            {
                loader:'css-loader'
            },
            {
                loader:'less-loader'
            }
            
        ]
    },
],

В приведенной выше конфигурации сначала выполняется less-loader, затем css-loader и, наконец, style-loader.

rules: [
    {
        test: /\.less$/,
        loader:'style-loader',
    },
    {
        test: /\.less$/,
        loader:'css-loader',
    },
    {
        test:/\.less$/,
        loader:'less-loader'
    }
],

В приведенной выше конфигурации сначала выполняется less-loader, затем css-loader и, наконец, style-loader.

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

Пять, контролировать порядок выполнения загрузчика

Управляется Rule.enforce, который имеет два значения:

  • pre: выполнить первым
  • post: последнее выполнение
rules: [
    {
        test:/\.less$/,
        loader:'less-loader'
    },
    {
        test: /\.less$/,
        loader:'css-loader',
    },
    {
        test: /\.less$/,
        loader:'style-loader',
    },
],

Если вы следуете указанному выше порядку написания, то сначала выполняется style-loader, затем css-loader и последним выполняется less-loader. Результат точно будет неверным. Вы можете использовать Rule.enforce для управления порядком выполнения загрузчиков. Он не меняет порядок записи загрузчика и может выполняться корректно.

rules: [
    {
        test:/\.less$/,
        loader:'less-loader',
        enforce:'pre'
    },
    {
        test: /\.less$/,
        loader:'css-loader',
    },
    {
        test: /\.less$/,
        loader:'style-loader',
        enforce:'post'
    },
],

На этом этапе сначала выполняется less-loader, затем css-loader и, наконец, style-loader.

На самом деле загрузчик также имеет «встроенное» использование. пример

import 'style-loader!css-loader!less-loader!./index.css';

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

Погрузчики здесь можно разделить на четыре типа

  • pre
  • normal
  • inline
  • post

Его порядок выполнения pre -> normal -> inline ->post

По возможности используйте module.rules, так как это уменьшает объем кода в исходном коде и ускоряет отладку и поиск проблем в загрузчике, когда что-то идет не так.

Использование «встроенных» загрузчиков не рекомендуется на официальном сайте Webpack, поэтому загрузчики встроенного типа исключаются, когда речь идет о порядке выполнения загрузчиков.

Шестое, настройте загрузчик в Vue Cli3.

Есть два способа настроить загрузчик в Vue Cli3, один черезconfigureWebpackвариант настройки, второй черезchainWebpackопции для настройки.

В конфигурации можно использоватьvue-cli-service inspectчтобы просмотреть конфигурацию веб-пакета проекта Vue CLI.

в проектеpackage.jsonв файлеscriptsдобавить команду в

"scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "inspect": "vue-cli-service inspect --mode production  > output.js"
},

inspectЭта команда означает вывод проанализированной конфигурации веб-пакета в производственной среде этого проекта вoutput.jsв этом файле.

если--mode development, который является конфигурацией веб-пакета в среде разработки.

настроить конфигурацию веб-пакета

configureWebpackЗначение параметра может быть объектом или функцией.

  • Значение является объектом.

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

    Например, вvue.config.jsСредняя конфигурация

    module.exports = {
        configureWebpack:{
            module:{
                rules:[
                    {
                        test:/\.less$/,
                        use:['style-loader','css-loader','less-loader']
                    }
                ]
            }
        },
    }
    

    воплощать в жизньnpm run inspectпосле, вoutput.jsбудет найдено, как показано на следующем рисунке

  • Значение представляет собой функцию.

    Функция получает конфигурацию в качестве параметра, а содержимое параметра — это конфигурация веб-пакета.В это время конфигурация веб-пакета может быть изменена с помощью параметра конфигурации, или объект может быть возвращен для объединения в окончательную конфигурацию с помощью веб-слияния. .

    Например, вvue.config.jsСредняя конфигурация

    module.exports = {
        configureWebpack:config =>{
            config.module.rules[10]={
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            }
        },
    }
    

    воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, конфигурация загрузчика, которая первоначально обрабатывала файл .less, была заменена измененной позже.

    Но использование этого метода для изменения конфигурации загрузчика слишком обширно.Если вы хотите более тонко изменить конфигурацию загрузчика, вы можете использоватьchainWebpackнастроить.

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

chainWebpackЗначение параметра — это функция, которая получит экземпляр ChainableConfig на основе цепочки веб-пакетов. использоватьЦепное письмонастроить вебпак.Документация по использованию нажмите здесь мы.

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

Добавить новое правило

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
    },
}

Условия добавления правил

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            //添加test选项
            .test(/\.less$/)
            //添加include选项,其值是数组
            .include.add('/src/').add('/view/').end()
            //添加exclude选项,其值是数组
            .exclude.add('/node_modules/').end()
            //添加issuer选项
            .issuer('/\main\.js$/')
            //添加resourceQuery选项
            .resourceQuery('/inline/')
    },
}

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, он создается с помощью приведенной выше конфигурации.

Вы также можете использовать Rule.resource для настройки условий правила, которое настраивается в chainWebpack следующим образом:

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            .issuer('/\main\.js$/')
            .resourceQuery('/inline/')
            //添加resource选项
            .resource({
                test:/\.less$/,
                include:['/src/','/view/'],
                exclude:['/node_modules/'],
            })
    },
}

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, он создается с помощью приведенной выше конфигурации.

Добавляем загрузчик правила Rule

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            //先创建一个具名的use,后面修改有用到这个名称
            .use('styleloader')
                //往这个具名的use中添加一个loader
                .loader('style-loader')
                //添加多个loader时要先.end()回到主链路
                .end()
            .use('cssloader')
                .loader('css-loader')
                .end()
            .use('lessloader')
                .loader('less-loader')
    },
}

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, он создается с помощью приведенной выше конфигурации. Обратите внимание на порядок написания, то, что написано последним, выполняется первым.

Добавляем параметры загрузчика правила Rule

Например, чтобы добавить параметры в less-loader.

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            .use('lessloader')
                .loader('less-loader')
                .options({
                    // 这里配置全局变量
                    globalVars: {
                        'primary': '#fff'
                    }
                })
                
    },
}

.options()Параметр является объектом, и параметры загрузчика настраиваются в объекте.

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, он создается с помощью приведенной выше конфигурации.

Изменить параметры загрузчика правила Rule

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            .use('lessloader')
            .tap(options =>{
                options.globalVars.primary= 'red';
                return options
            })  
    },
}

использовать.tap()Для этого его параметром является функция, а параметром функции являются исходные параметры набора параметров объекта загрузчика.Изменяя параметры параметров, а затем возвращая параметры, цель изменения параметров загрузчика правила достигнуто.

перед фиксацией

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, он создается после вышеуказанной модификации.

Изменить загрузчик правила Правило

перед фиксацией

Есть два подхода

  • Изменить один из загрузчиков
module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            .use('lessloader')
                .loader('sass-loader')
    },
}

после модификации

  • Все это правило, загрузчик для очистки повторно добавить
module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            .uses.clear()
                .end()
            .use('styleloader')
                .loader('style-loader')
    }
}

после модификации

Создать группу правил Rule.oneOf

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            .test(/\.less$/)
            .oneOf('vue-modules')
                .resourceQuery('/module/')
                .use('css-loader')
                    .loader('css-loader')
                    .end()
                .use('less-loader')
                    .loader('less-loader')
                    .end()
                .end()
            .oneOf('src')
                .resourceQuery('/src/')
                .use('style-loader')
                    .loader('style-loader')
                    .end()
                .use('css-loader')
                    .loader('css-loader')
                    .end()
                .use('less-loader')
                    .loader('less-loader')
    }
}

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, он создается с помощью приведенной выше конфигурации.

Изменить группу правил Rule.oneOf

Перед созданием группы правил Rule.oneOf мы дали каждому Rule.oneOf имя, которое можно использовать.oneOf(name)Ищете это правило. ROOF Изменить, редактировать и создать тот же синтаксис.

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule')
            .oneOf('vue-modules')
            .resourceQuery('/module11/')
            .use('css-loader')
                .loader('sass-loader')
    }
}

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что измененный результат показан на следующем рисунке.

Контролировать порядок выполнения загрузчиков

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule1')
            .test(/\.less$/)
            .use('lessloader')
            .loader('less-loader')
        config.module
            .rule('myRule2')
            .test(/\.less$/)
            .use('styleloader')
            .loader('style-loader')
        config.module
            .rule('myRule3')
            .test(/\.less$/)
            .use('cssloader')
            .loader('css-loader')
    }
}

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, он создается с помощью приведенной выше конфигурации.

Потому что по условиям одного и того же правила загрузчики в правиле пишутся позже и выполняются первыми.

Все условия в одном правилеtest(/\.less$/)Далее запускаем сначала css-loader, потом style-loader и наконец less-loader, такой порядок выполнения точно не правильный. Сначала вы должны выполнить less-laoder, затем css-loader и, наконец, style-loader.

Это доступно.pre(),.post(),.enforce('pre'/'post')контролировать порядок выполнения загрузчика.

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule1')
            .test(/\.less$/)
            .use('lessloader')
            .loader('less-loader')
            .end()
            .pre()
        config.module
            .rule('myRule2')
            .test(/\.less$/)
            .use('styleloader')
            .loader('style-loader')
            .end()
            .post()
        config.module
            .rule('myRule3')
            .test(/\.less$/)
            .use('cssloader')
            .loader('css-loader')
    }
}

воплощать в жизньnpm run inspectпосле, вoutput.jsВы обнаружите, что, как показано на рисунке ниже, он создается с помощью приведенной выше конфигурации.

В настоящее время порядок выполнения загрузчика таков: сначала выполнить less-loader, затем выполнить css-loader и, наконец, выполнить style-loader.

Или это также может быть достигнуто

module.exports = {
    chainWebpack: config =>{
        config.module
            .rule('myRule1')
            .test(/\.less$/)
            .use('lessloader')
            .loader('less-loader')
            .end()
            .enforce('pre')
        config.module
            .rule('myRule2')
            .test(/\.less$/)
            .use('styleloader')
            .loader('style-loader')
            .end()
            .enforce('post')
        config.module
            .rule('myRule3')
            .test(/\.less$/)
            .use('cssloader')
            .loader('css-loader')
    }
}