Предупреждение: проверьте, как установлена версия 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");
});
}
Поддержка динамических выражений при загрузке модулей — 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
.
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 (https://github.com/webpack/enhanced-resolve). Она стала гибче, а вероятность настроить что-то неправильно снизилась.
Новые опции:
{
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
теперь всегда работают асинхронно, даже если чанк уже загружен.
Ссылки:
P.S. — Замечания, предложения — пожалуйста, в ЛС
Автор: DevExpress