webpack4.0 оптимизирует эти вещи

Node.js сервер JavaScript Webpack

1 Сузить поиск файлов

1 include & exclude

1) action

  • Ограничить область компиляции

2) useage

module: {
        rules: [
            {
                test: /\.js$/,
                use: ['babel-loader?cacheDirectory'],
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/
            }
        ]
    }

'babel-loader?cacheDirectory'

You can also speed up babel-loader by as much as 2x by using the cacheDirectory option. This will cache transformations to the filesystem.

QA

предупреждение командной строки

[BABEL] Note: The code generator has deoptimised the styling of "/Users/xxx/Documents/xxx/webpack_test/test3/node_modules/lodash/lodash.js" as it exceeds the max of "500KB".

Добавление диапазона ограничения исключения не приведет к сообщению об ошибке

2 resolve.modules

1) action

  • Tell webpack what directories should be searched when resolving modules.

2) useage

resolve: {
    modules: [path.resolve('node_modules'), path.resolve('lib')]
}

3) note

  • Absolute and relative paths can both be used, but be aware that they will behave a bit differently.

  • A relative path will be scanned similarly to how Node scans for node_modules, by looking through the current directory as well as it's ancestors (i.e. ./node_modules, ../node_modules, and on).

  • With an absolute path, it will only search in the given directory.

  • Если вы хотите добавить каталог для поиска, который имеет приоритет над node_modules/: (то есть по порядку)

modules: [path.resolve(__dirname, "src"), "node_modules"]

4) QA

Module not found: Error: Can't resolve 'ajax' in '/Users/xxx/Documents/xxx/webpack_test/test3/src'

Когда вам нужно указать другие каталоги модулей, кроме node_modules, вы можете добавить атрибуты в массив

3 resolve.mainFields

1) action

  • Resolve.mainFields в конфигурации Webpack используется для настройки того, какой файл записи используется сторонними модулями.

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

Причина, по которой может быть несколько полей, описывающих входной файл, заключается в том, что некоторые модули могут использоваться в нескольких средах одновременно, и для разных сред выполнения необходимо использовать разный код. Возьмем в качестве примера API-интерфейс isomorphic-fetch, который является реализацией Promise, но может использоваться как в браузере, так и в среде Node.js.

2) useage

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

module.exports = {
  resolve: {
    // 只采用 main 字段作为入口文件描述字段,以减少搜索步骤
    mainFields: ['main'],
  },
};

4 resolve.alias

1) action

  • Элемент конфигурации сопоставляет исходный путь импорта с новым путем импорта через псевдоним.
  • Этот метод оптимизации влияет на использование Tree-Shaking для удаления мертвого кода.

2) useage

alias: {
    "bootstrap": "bootstrap/dist/css/bootstrap.css"
}

5 resolve.extensions

1) action

  • Когда оператор импорта не имеет суффикса файла, Webpack автоматически добавит суффикс, чтобы попытаться спросить, существует ли файл -
  • Суффикс по умолчанию — расширения: ['.js', '.json']

2) useage

3) note

  • Старайтесь, чтобы список суффиксов был как можно меньше.
  • Самая высокая частота идет вперед
  • Максимально используйте суффиксы в операторах экспорта

6 module.noParse

1) action

  • Элемент конфигурации module.noParse позволяет Webpack игнорировать рекурсивный анализ некоторых файлов, которые не являются модульными.

2) useage

module: {
    noParse: [/react\.min\.js/]
}

2) note

Игнорируемые файлы не должны содержать import , require , define и другие модульные операторы.

Две DLL

1 action

Файл с dll в качестве суффикса называется динамической библиотекой, Динамическая библиотека может содержать функции и данные, вызываемые другими модулями.

  • Разделите базовые модули на отдельные динамически подключаемые библиотеки.
  • Когда импортируемый модуль находится в динамической библиотеке, модуль не может быть снова упакован, но получен из динамической библиотеки.

2 usage

Определить подключаемый модуль (DLLPlugin) ---> Ссылочный подключаемый модуль (DllReferencePlugin)

В этом примере используется jquery в качестве примера

1) Определите DLL

  • Используется для упаковки библиотеки динамической компоновки.
  • нужно строить отдельно

webpack.jquery.config.js

module.exports = {
    entry: ["jquery"],
    output: {
        filename: "vendor.js",
        path: path.resolve(__dirname, "dist"),
        libraryTarget: 'var',// 打包的方式,hou
        library: "vendor_lib_vendor"// DLL的名字
    },
    plugins: [
        new webpack.DllPlugin({
            name: "vendor_lib_vendor",// 定义DLL
            path: path.resolve(__dirname, "dist/vendor-manifest.json")
        })
    ]
};

Добавьте скрипты в package.json

"dll": "webpack --config webpack.jquery.config.js --mode development"

После настройки вышеуказанных файлов запустите в терминалеnpm run dll, в каталоге dist будут сгенерированы два файла,vendor.jsа такжеvendor-manifest.json.vendor.jsВ комплекте есть упакованныйjqueryкод файла,vendor-manifest.jsonиспользуется для ассоциации. DLL определена, и следующим шагом является применение упакованной DLL.

2) Справочная DLL

Библиотека динамической компоновки, упакованная плагином DllPlugin, внесена в конфигурационный файл webpack.config.js.

plugins: [
        new webpack.DllReferencePlugin({
            context: __dirname,
            manifest: require("./dist/vendor-manifest.json")
        })
    ],

3) Использование DLL

app.html Добавить внизу app.html

<script src="./vendor.js"></script>

3 note

libraryTargetа такжеlibrary

Они необходимы при использовании Webpack для создания библиотеки, которую можно импортировать и использовать другими модулями.

  • output.libraryTarget настраивает способ экспорта библиотеки.
  • output.library настраивает имя библиотеки экспорта. Обычно они используются вместе.

output.libraryTarget — это тип перечисления строк, который поддерживает следующие конфигурации.

1) переменная (по умолчанию)

Написанная библиотека будет назначена через var переменной с именем via library.

Если output.library='LibraryName' настроен, выходные и используемые коды следующие:

// Webpack 输出的代码
var LibraryName = lib_code; //其中 lib_code 代指导出库的代码内容,是有返回值的一个自执行函数。

// 使用库的方法
LibraryName.doSomething();

2) commonjs

Написанные библиотеки будут экспортированы через спецификацию CommonJS.

Если output.library='LibraryName' настроен, выходные и используемые коды следующие:

// Webpack 输出的代码
exports['LibraryName'] = lib_code;

// 使用库的方法
require('library-name-in-npm')['LibraryName'].doSomething();
// 其中 library-name-in-npm 是指模块发布到 Npm 代码仓库时的名称。

3) commonjs2

Написанная библиотека будет экспортирована через спецификацию CommonJS2, а код вывода и использования будет следующим:

// Webpack 输出的代码
module.exports = lib_code;

// 使用库的方法
require('library-name-in-npm').doSomething();

Спецификации CommonJS2 и CommonJS очень похожи, разница в том, что CommonJS можно экспортировать только экспортами, а CommonJS2 добавляет метод экспорта module.exports на основе CommonJS. Когда output.libraryTarget имеет значение commonjs2, настройка output.library не имеет смысла.

4) this

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

// Webpack 输出的代码
this['LibraryName'] = lib_code;

// 使用库的方法
this.LibraryName.doSomething();

5) window

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

// Webpack 输出的代码
window['LibraryName'] = lib_code;

// 使用库的方法
window.LibraryName.doSomething();

6) global

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

// Webpack 输出的代码
global['LibraryName'] = lib_code;

// 使用库的方法
global.LibraryName.doSomething();

Три счастливых пакета

1 action

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

2 usage

install

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

npm i happypack@next -D

webpack.config.js

module: {
        rules: [
            {
                test: /\.css$/,
                use: 'happypack/loader?id=css',
                //把对.js文件的处理转交给id为babel的HappyPack实例
                //用唯一的标识符id来代表当前的HappyPack是用来处理一类特定文件
                include: path.resolve('./src'),
                exclude: /node_modules/
            },
            {
                test: /\.js/,
                use: 'happypack/loader?id=babel',
                include: path.resolve('./src'),
                exclude: /node_modules/
            }
        ]
    },
    plugins: [
        new HtmlWebPackPlugin({
            template: './src/index.html'
        }),
        new HappyPack({
            id: 'babel',
            loaders: ['babel-loader']// 和rules里的配置相同
        }),
        new HappyPack({
            id: 'css',
            loaders: ['style-loader', 'css-loader']// 和rules里的配置相同
        }),
    ]

Плагин Four ParallelUglify

1.action

  • Вы можете превратить последовательное сжатие файлов JS в открытие нескольких подпроцессов для параллельного выполнения.

2 usage

insatll

npm install webpack-parallel-uglify-plugin -D

webpackage.config.js

new ParallelUglifyPlugin({
            workerCount: os.cpus().length - 1,//开启几个子进程去并发的执行压缩。默认是当前运行电脑的 CPU 核数减去1
            uglifyJS: {
                output: {
                    beautify: false, //不需要格式化
                    comments: true, //不保留注释
                },
                compress: {
                    warnings: false, // 在UglifyJs删除没有用到的代码时不输出警告
                    drop_console: true, // 删除所有的 `console` 语句,可以兼容ie浏览器
                    collapse_vars: true, // 内嵌定义了但是只用到一次的变量
                    reduce_vars: true, // 提取出出现多次但是没有定义成变量去引用的静态值
                }
            }
        })

Автоматическое обновление пяти серверов

1 файловый монитор

1) action

  • Вы можете отслеживать изменения файлов и перекомпилировать их при изменении файла.

2) useage

watch: true, 
watchOptions: {
    ignored: /node_modules/,
    aggregateTimeout: 300, 
    poll: 1 
}

3) note

watch

watchOptions имеет смысл только при включенном режиме прослушивания (watch true)

aggregateTimeout

После отслеживания изменения подождите 300 (мс) перед выполнением действия, чтобы предотвратить слишком быстрое обновление файла и слишком высокую частоту компиляции.

poll

Определите, изменился ли файл, постоянно спрашивая, изменился ли файл, по умолчанию 1000 раз в секунду.

процесс мониторинга файлов

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

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

webpack будет прослушивать только те файлы, от которых зависит запись Нам нужно минимизировать количество файлов, которые необходимо контролировать, и частоту проверки, естественно, уменьшение частоты приведет к снижению чувствительности.

2 Автоматически обновлять браузер

1) use

devServer: {
    inline: true
},

2) note

webpack отвечает за мониторинг изменений файлов, а webpack-dev-server отвечает за обновление браузера. Эти файлы будут упакованы в куски, которые будут проксировать клиента, чтобы инициировать соединение WebSocket с сервером.

3 модуля горячей замены

1) action

  • Технология горячей замены модуля позволяет обновить только указанный модуль, не обновляя всю веб-страницу.
  • Принцип заключается в том, что при изменении исходного кода перекомпилируется только измененный модуль, а соответствующий старый модуль в браузере заменяется новым выходным модулем.

2) Преимущества

  • Более быстрый отклик и меньшее время
  • Рабочее состояние веб-страницы можно сохранить без обновления веб-страницы.
  • Слушайте меньше файлов
  • Игнорировать файлы в каталоге node_modules

2) use

webpack.config.js

devServer: {
   hot:true//将hot设置为true
},

// 需要的插件
plugins: [
    new webpack.NamedModulesPlugin(),//显示模块的相对路径
    new webpack.HotModuleReplacementPlugin()// 启动热加载功能
]

code

if (module.hot) {
    module.hot.accept('./hot.js', () => {
        let hot = require('./hot');
        document.getElementById('app2').innerHTML = hot + '1';
    })
}

3 note

Модули, требующие горячей загрузки, необходимо вводить в модуль во время инициализации, иначе HMR не сработает.

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

1 action

При разработке веб-страницы обычно используется несколько наборов работающих сред, например среда, облегчающая разработку и отладку в процессе разработки. Среда выполнения, опубликованная в Интернете для использования пользователями.

Основные отличия онлайн-среды от среды разработки заключаются в следующем:

  • Код в строке сжат
  • Среда разработки может печатать журналы, которые могут видеть только разработчики.
  • Внутренний интерфейс данных среды разработки и онлайн-среды может отличаться

2 usage

package.json

  • cross-envУстановите кросс-платформенные переменные среды (без && после него)
"scripts": {
    "build-dev": "cross-env NODE_ENV=development webpack --mode development",
    "build-prod": "cross-env NODE_ENV=production webpack --mode production"
}

webpack.config.js

  • Различать производственную среду и среду разработки в соответствии с переменными среды, а затем иwebpack.base.config.jsСлияние, производственная среда (или среда разработки) имеет более высокий приоритетwebpack.base.config.jsКонфигурация.
let merge = require('webpack-merge');
let base = require('./webpack.base.config');
let other = null;
if (process.env.NODE_ENV === 'development') {
    other = require('./webpack.dev.config');
} else {
    other = require('./webapack.prod.config');
}
module.exports = merge(base, other);

webpack.base.config.js

  • базовая конфигурация
  • webpack.DefinePluginопределить переменные среды
基本配置...
plugins: [
    new webpack.DefinePlugin({
        __isDevelopment__: JSON.stringify(process.env.NODE_ENV == 'development')
    })
]

webpack.dev.config.js

  • кoutputНапример, если параметры среды разработки и производственной среды различаются, он будет перезаписан.webpack.base.config.jsконфигурация внутри
const path = require('path');
module.exports = {
    output: {
        path: path.resolve('./dist'),
        filename: "[name].dev.[hash:2].js"
    }
};

webpack.prod.config.js

  • outputНапример)
const path = require('path');
module.exports = {
    output: {
        path: path.resolve('./dist'),
        filename: "[name].prod.[hash:8].js"
    }
};

base.js

  • в файле конфигурацииwebpack.DefinePluginОпределенные переменные (__isDevelopment__), который можно получить в файле входа и других файлах, на которые ссылается файл входа__isDevelopment__значение
let env = null;
if (__isDevelopment__) {
    env = 'dev';
} else {
    env = 'prod';
}
module.exports = env;

index.js

let env = require('./base.js');
if (__isDevelopment__) {
    console.log('dev');
} else {
    console.log('prod');
}
console.log('env', env);

/*
prod
env prod
*/

3 note

webpack.DefinePlugin

Причина переноса строки с помощью JSON.stringify при определении значения переменной среды заключается в том, что значение переменной среды должно быть строкой, заключенной в двойные кавычки, а значение JSON.stringify('production') точно равно равно «производству»

Семь CDN

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

  • HTML-файлы не кешируются, они размещаются на вашем собственном сервере, кеш вашего собственного сервера отключается, а URL-адрес статического ресурса становится адресом, указывающим на CDN-сервер
  • Статические файлы JavaScript, CSS, изображения и другие файлы включают CDN и кеш, а также имена файлов со значениями HASH.
  • Чтобы загружать параллельно без блокировки, выделяйте разные статические ресурсы на разные CDN-серверы.

Встряхивание восьмого дерева

1 action

Tree Shaking можно использовать для отсеивания неиспользуемого мертвого кода в JavaScript.

2 useage

  • Он основан на статическом модульном синтаксисе ES6, таком как импорт и экспорт через импорт и экспорт.
  • Не компилируйте модули ES6
use: {
    loader: 'babel-loader',
    query: {
        presets: [
            [
                "env", {
                    modules: false //含义是关闭 Babel 的模块转换功能,保留原本的 ES6 模块化语法
                }
            ],
            "react"
        ]
    }
},

3 note

Обратите внимание, что он основан на статическом модульном синтаксисе ES6, таком как импорт и экспорт через импорт и экспорт. То есть, если код проекта работает в среде, не поддерживающей синтаксис es6, Tree Shake не имеет смысла.

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

1 Зачем вам нужно извлекать публичный код

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

Одни и те же ресурсы загружаются повторно, что приводит к трате пользовательского трафика и затрат на сервер; Ресурсы, которые необходимо загрузить для каждой страницы, слишком велики, что приводит к медленной загрузке первой страницы веб-страницы и влияет на взаимодействие с пользователем. Если общий код можно извлечь в отдельный файл для загрузки, его можно оптимизировать, что может уменьшить трафик передачи по сети и снизить затраты на сервер

2 Как извлечь

1) Классификация

Разные типы файлов имеют разные блоки кода после упаковки:

  • Базовая библиотека классов для долгосрочного кэширования
  • Общий код между страницами
  • Отдельные файлы для каждой страницы

2) usage

webpack.config.js

 optimization: {
        splitChunks: {
            cacheGroups: {
                commons: {// 页面之间的公用代码
                    chunks: 'initial',
                    minChunks: 2,
                    maxInitialRequests: 5, // The default limit is too small to showcase the effect
                    minSize: 0 // This is example is too small to create commons chunks
                },
                vendor: {// 基础类库
                    chunks: 'initial',
                    test: /node_modules/,
                    name: "vendor",
                    priority: 10,
                    enforce: true
                }
            }
        }
    },

./src/pageA.js

require('./utils/utility1.js');
require('./utils/utility2.js');
require('react');

./src/pageB.js

require('./utils/utility2.js');
require('./utils/utility3.js');

./src/pageC.js

require('./utils/utility2.js');
require('./utils/utility3.js');

utils/utility1.js

module.exports = 1;

utils/utility2.js

module.exports = 2;

utils/utility3.js

module.exports = 3;

упакованный результат

Сгенерированные результаты трех вышеуказанных кодов следующие:

提取公共代码

Подъем с десятью сферами

1 action

Scope Hoisting может уменьшить размер файлов кода, упакованных Webpack, и ускорить их работу.Это также переводится как «подъем объема» и представляет собой новую функцию, представленную в Webpack3.

  • Меньший размер кода, потому что объявления функций генерируют много кода
  • Когда код выполняется, поскольку созданная область действия меньше, накладные расходы памяти также уменьшаются hello.js

2 useage

package.json

 "build": "webpack  --display-optimization-bailout --mode development",

webpack.config.js

plugins: [
    new ModuleConcatenationPlugin()
    ],

./h.js

export default 'scope hoist'

./index.js

import str from './h.js'
console.log(str);

3 note

Необходимо использовать синтаксис ES6, иначе он не работает (--display-optimization-bailoutпараметры будут запрошены)

Разделение одиннадцати кодов

Разделение кода — одна из самых ярких особенностей webpack. Эта функция разделяет код на разные пакеты, которые затем можно загружать по запросу или параллельно. Существует три распространенных метода разделения кода:

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

О точке входа и предотвращении повторов было сказано выше, остановимся на динамическом импорте.

1 action

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

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

2 usage

  • использоватьimport(module)синтаксис
  • импорт модуля асинхронной загрузки - это синтаксис es7
  • Импорт является естественной точкой разделения в веб-пакете.
document.getElementById('play').addEventListener('click',function(){
    import('./vedio.js').then(function(video){
        let name = video.getName();
        console.log(name);
    });
});

Справочная документация