Предупреждение: проверьте, как установлена версия Webpack в package.json. Возможно скоро ваш continuous integration сломается.
Наконец-то Webpack 2 преодолел рубеж beta и release candidate. Это значит, что всё работает стабильно, и можно без опаски использовать его в production.
Список изменений/улучшений:
- Нативная поддержка ES6-модулей;
- Разбиение кода на чанки — Code Splitting with ES6;
- Поддержка динамических выражений при загрузке модулей — Dynamic expressions;
- Изменения при работе с Babel;
- ES6-специфичные оптимизации;
- Breaking Changes;
- Новый сайт с документацией.
Нативная поддержка ES6-модулей
Теперь Webpack для работы с модулями поддерживает конструкции с использованием ключевых слов import
и export
без предварительной трансформации кода в CommonJS, и делает это весьма хорошо. Чтобы убедиться в гибкости поддержки, давайте взглянем на следующий код:
import { currentPage, readPage } from "./book";
currentPage === 0; //true
readPage();
currentPage === 1; //true
// book.js
export var currentPage = 0;
export function readPage() {
currentPage++;
}
export default "This is a book";
Разбиение кода на чанки — Code Splitting with ES6
Использование System.import
предоставляет возможность отложенной загрузки модулей в рантайме.
Если какой-либо модуль загружается с помощью System.import
, Webpack отделит его от остального кода в независимый chunk
.
System.import
принимает имя модуля/путь к модулю и возвращает Promise
, так что его использование отлично сочетается с async/await
;
function onClick() {
System.import("./module").then(module => {
module.default;
}).catch(err => {
console.log("Chunk loading failed");
});
}
UPDATE:
System.import will be deprecated in webpack 2 release (removed in webpack 3) as it's behavior is incorrect according to the spec
import() должен быть использован вместо System.import()
Поддержка динамических выражений при загрузке модулей — Dynamic expressions
Если использовать System.import
с динамическим выражением в качестве пути к модулю, то Webpack упакует код, каждого из модулей, соответствующих паттерну, в отдельный chunk
.
function route(path, query) {
return System.import("./routes/" + path + "/route")
.then(route => new route.Route(query));
}
// This creates a separate chunk for each possible route
Изменения при работе с Babel
Привычный всем babel-preset es2015
, по-умолчанию, трансформирует ES6 модули в CommonJS. Вместо него теперь нужно использовать babel-preset es2015-webpack
.
UPDATE:
babel-preset es2015-webpack объявлен deprecated вместо него нужно использовать опции:
{
"presets": [
[ "es2015", { "modules": false } ]
]
}
ES6-специфичные оптимизации
Статический характер ES6 модулей открывает возможности для новых оптимизаций на этапе компиляции. Например, теперь Webpack сможет находить неиспользуемые export-ы и удалять их — Tree-shaking.
Так же заявлена поддержка ES6 export mangling — минификация имени экспортируемой переменной или функции, если это возможно.
Изменения в конфигурационном файле
Раньше во многих Webpack-конфигах для настройки опциональных параметров использовались переменные окружения. Webpack 2 превносит еще один способ их определения извне.
Теперь при запуске Webpack-а через командную строку можно указать один или несколько аргументов --env
в следующем формате: (--env dev
=> "dev"
) или (--env.minimize --env.server localhost
=> {minimize: true, server: "localhost"}
). Рекомендуется использовать второй вариант.
// webpack.config.babel.js
exports default function(options) {
return {
// ...
devtool: options.dev ? "cheap-module-eval-source-map" : "hidden-source-map"
};
}
Много улучшений в подсистеме Webpack-а, отвечающей за resolving. Она стала гибче, а вероятность настроить что-то неправильно снизилась.
Новые опции:
{
modules: [path.resolve(__dirname, "app"), "node_modules"]
// (was split into `root`, `modulesDirectories` and `fallback` in the old options)
// In which folders the resolver look for modules
// relative paths are looked up in every parent folder (like node_modules)
// absolute paths are looked up directly
// the order is respected
descriptionFiles: ["package.json", "bower.json"],
// These JSON files are read in directories
mainFields: ["main", "browser"],
// These fields in the description files are looked up when trying to resolve the package directory
mainFiles: ["index"]
// These files are tried when trying to resolve a directory
aliasFields: ["browser"],
// These fields in the description files offer aliasing in this package
// The content of these fields is an object where requests to a key are mapped to the corresponding value
extensions: [".js", ".json"],
// These extensions are tried when resolving a file
enforceExtension: false,
// If false it will also try to use no extension from above
moduleExtensions: ["-loader"],
// These extensions are tried when resolving a module
enforceModuleExtension: false,
// If false it's also try to use no module extension from above
alias: {
jquery: path.resolve(__dirname, "vendor/jquery-2.0.0.js")
}
// These aliasing is used when trying to resolve a module
}
Breaking changes
Polyfills
Динамическая загрузка чанков теперь будет работать только, если Promise
доступен. Так что если необходима поддержка старых браузеров, то обеспечивать поддержку Promise
через полифилы нужно будет самому разработчику web-приложения.
Сделано это для того, чтобы избежать дублирования кода Promise-полифилов в разных частях bundle-js.
Так же для старых браузеров через полифилы необходимо обеспечть поддержку следующих функций:
Object.defineProperty
,
Function.prototype.bind
,
Object.keys
Loaders configuration
Webpack-loaders теперь конфигурируются с помощью параметра resourcePath
вместо resource
. Это означает, что query string больше не участвуют regex-matching.
Теперь вместо сложных конструкций вроде /\.svg($|\?)/
достаточно просто /\.svg$/
.
Синтаксис использования Webpack-loaders выглядит следующим образом:
loaders: [
{
test: /\.css$/,
loaders: [
"style-loader",
{ loader: "css-loader", query: { modules: true } },
{
loader: "sass-loader",
query: {
includePaths: [
path.resolve(__dirname, "some-folder")
]
}
}
]
}
]
HMR communication
Webpack 1 для уведомлений о пересборке бандла использовал Web Messaging API (postMessage). Webpack 2 использует стандартный event emitter. Это означает, что обвязка для WebSocket будет включена в бандл.
webpack-dev-server теперь по-умолчанию использует режим "inlined".
Это должно позволить использовать webpack-dev-server для горячей замены кода в Web Workers.
Code Splitting
require.ensure
и AMD require
теперь всегда работают асинхронно, даже если чанк уже загружен.
Ссылки:
Комментарии (19)
pribilinskiy
19.01.2017 11:42+1Забыли упомянуть что на данный момент он все еще инсталлится с тегой beta
npm install webpack@beta
Но через неделю обещают перевести вlatest
mihap
19.01.2017 12:16+1https://github.com/mihap/webpack-react-hot-bolerplate
Проапдейтил свой бойлерплейт. Кроме webpack v2.2.0 там еще react-router v4-alpha.6 и react-hot-loader v3-beta.6
Можно использовать и для продакшн, с верой в удачу и оптимизмом =), но скорее как пример конфига для апгрейда.MrCheater
19.01.2017 13:11
reactoranime
19.01.2017 13:11Интересно, есть где-нибудь рабочие сборки с babel-polyfill для IE11? А еще лучше разбитые на части vendor/bundle chunks, с использованием CommonChunksPlugin. Сколько не пробовал, выглядит как костыль, и толком не работает. Есть кто сталкивался с этим?
k12th
19.01.2017 12:28По-моему, самое ценное изменение — появление человекочитаемой документации:) И даже конфиг стал чуть понятнее (хотя еще есть куда расти).
raveclassic
19.01.2017 12:44+1Действительно, какого же было мое удивление, когда я первый раз попал в новые доки.
Defari
19.01.2017 13:01+3В настройках лоадера, query: {} не является валидным параметром. Нужно использовать options: {}.
Vahan
25.01.2017 15:41Одна проблема: uglify-js пока что не перешел на ES6, так что приходиться использовать harmony бренч.
"uglify-js": "git://github.com/mishoo/UglifyJS2#harmony",
reactoranime
25.01.2017 17:06а как же быть с плагином для webpack:
new webpack.optimize.UglifyJsPlugin({ compress: { // warnings: false, // drop_console: true }, output: { comments: false } })
Vahan
25.01.2017 17:30О чем вы? Это он и есть ( https://github.com/webpack/webpack/blob/v2.2.0/package.json ), добовляем в dependencies ту строку, чтоб взял с другого бренча.
BoryaMogila
Спасибо за статью.