Первый официальный релиз Webpack 2. Что нового по сравнению с Webpack 1?

в 5:32, , рубрики: javascript, node.js, ReactJS, release, webpack, webpack 2, Блог компании DevExpress, Программирование, релиз

Webpack 2 Release

Предупреждение: проверьте, как установлена версия 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.

Can I use Promises?

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

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 теперь всегда работают асинхронно, даже если чанк уже загружен.

Ссылки:

  1. Webpack 2.2: The Final Release
  2. Новый сайт с докментацией
  3. Migrating from v1 to v2

Картинка из официального блога Webpack на Medium

P.S. — Замечания, предложения — пожалуйста, в ЛС

Автор: DevExpress

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js