ЕС6 модули који дрхте у дрвету 2

Вебпацк 2 је управо пуштен из бета верзије прошле недеље. Са собом доноси разне очекиване функције, укључујући нативну подршку за ЕС6 модуле.

Уместо да користи var module = require('module')синтаксу, вебпацк 2 подржава ЕС6 importsи exports. Ово отвара врата за оптимизацију кода попут дрхтања дрвета .

Шта је дрхтање?

Популаризовано пакетом модула Рицх Харрис 'Роллуп.јс, дрмање дрвећа је способност да се у ваш пакет укључи само код који се користи.

Када сам се први пут поиграо са Роллупом, био сам запањен како добро функционише са ЕС6 модулима. Развојно искуство се управо осетило ... како треба. Могао бих да створим засебне модуле написане у „будућем ЈаваСцрипт-у“, а затим их укључим било где у свом коду. Било који код који остане неискориштен не улази у мој пакет. Геније!

Који проблем решава?

Ако пишете ЈаваСцрипт 2017. године и разумете (погледајте: Замор ЈаваСцрипт-а) разне алате око себе, ваше развојно искуство се вероватно осећа прилично флуидно. Ово је важно, али оно што је такође важно је корисничко искуство . Много ових модерних алата на крају напухује веб апликације масивним ЈаваСцрипт датотекама, што резултира споријим перформансама.

Оно што ми се свиђа код Роллупа је то што се погоди по овом питању и доноси решење у први план ЈаваСцрипт заједнице. Сада велика имена попут вебпацк-а покушавају да га понављају.

Дрхтање дрвећа можда није „решење за завршетак свих решења“, али је важан део веће пите.

Једноставан пример

Пре него што започнете, желим вам пружити тривијални пример дрмања. Ваша апликација се састоји од 2 датотеке index.jsи module.js.

Изнутра module.jsизвозите 2 именоване функције стрелице:

// module.js export const sayHello = name => `Hello ${name}!`; export const sayBye = name => `Bye ${name}!`

Само sayHelloсе увози у index.jsфајлу:

// index.js import { sayHello } from './module'; sayHello('World');

sayByeсе извози, али никада не увози. Било куда. Због тога, због дрхтања дрвета, неће бити укључено у ваш пакет:

// bundle.js const sayHello = name => `Hello ${name}!`; sayHello('World');

Овисно о кориштеном пакету, горња излазна датотека може изгледати другачије. То је само поједностављена верзија, али схватате.

Недавно сам прочитао чланак који је написао Роман Лиутиков, и направио је сјајну аналогију како би визуализовао концепт дрхтања дрвећа:

„Ако се питате зашто се то зове дрхтање: замислите своју апликацију као графикон зависности, ово је стабло, а сваки извоз је грана. Па ако протресете дрво, мртве гране ће пасти. “ - Роман Лиутиков

Тресење дрвета у веб пакету 2

Нажалост за оне од нас који користимо вебпацк, дрмање дрвећа је „иза прекидача“, ако желите. За разлику од Роллупа, потребно је извршити одређену конфигурацију пре него што добијете функционалност коју тражите. Део „иза прекидача“ може неке људе збунити. Објаснићу.

Корак 1: Подешавање пројекта

Претпоставићу да разумете основе вебпацк-а и да се можете снаћи у основној конфигурационој датотеци вебпацк-а.

Почнимо са стварањем новог директоријума:

mkdir webpack-tree-shaking && cd webpack-tree-shaking

Кад уђемо унутра, покренимо нови npmпројекат:

npm init -y

-yОпција генерише package.jsonбрзо, без потребе за одговорите на гомилу питања.

Даље, хајде да инсталирамо неколико зависности од пројекта:

npm i --save-dev [email protected] html-webpack-plugin

Горња команда ће инсталирати најновију бета верзију вебпацк-а 2 локално у ваш пројекат, као и корисни додатак под називом html-webpack-plugin. Ово последње није неопходно за циљ овог упутства, али ће ствари учинити нешто бржим.

Напомена : Команду npm i --save-dev [email protected]и даље препоручује тим вебпацк-а у време писања овог текста. [email protected]на крају ће бити укинут у корист webpackнајновије команде. Погледајте како да преузмете?одељак најновијег издања вебпацка за више детаља.

Отворите package.jsonи уверите се да су инсталирани као devDependencies.

Корак 2: Креирајте ЈС датотеке

Да бисте видели дрмање дрвета на делу, потребно је да имате ЈаваСцрипт за играње. У корену вашег пројекта креирајте srcфасциклу са 2 датотеке у себи:

mkdir src && cd src touch index.js touch module.js

Напомена:touch команда креира нову датотеку преко терминала.

Копирајте доњи код у исправне датотеке:

// module.js export const sayHello = name => `Hello ${name}!`; export const sayBye = name => `Bye ${name}!`;
// index.js import { sayHello } from './module'; const element = document.createElement('h1'); element.innerHTML = sayHello('World'); document.body.appendChild(element);

Ако сте стигли толико далеко, структура фасцикле би требало да изгледа овако:

/ | - node_modules/ | - src/ | | - index.js | | - module.js | - package.json

Корак 3: Вебпацк из ЦЛИ

Since you have no configuration file created for your project, the only way to get webpack to do any work at the moment is through the webpack CLI. Let’s perform a quick test.

In your terminal, run the following command in your project’s root:

node_modules/.bin/webpack

After running this command, you should see output like this:

No configuration file found and no output filename configured via CLI option. A configuration file could be named 'webpack.config.js' in the current directory. Use --help to display the CLI options.

The command doesn’t do anything, and the webpack CLI confirms this. You haven’t given webpack any information about what files you want to bundle up. You could provide this information via the command line or a configuration file. Let’s choose the former just to test that everything is working:

node_modules/.bin/webpack src/index.js dist/bundle.js

What you’ve done now is pass webpack an entry file and an output file via the CLI. This information tells webpack, "go to src/index.js and bundle up all the necessary code into dist/bundle.js". And it does just that. You'll notice that you now have a dist directory containing bundle.js.

Open it up and check it out. There’s some extra javascript in the bundle necessary for webpack to do its thing, but at the bottom of the file you should see your own code as well.

Step 4: Create a webpack configuration file

Webpack can handle a lot of things. I’ve spent a good chunk of my free time diving into this bundler and I still have barely scratched the surface. Once you’ve move passed trivial examples its best to leave the CLI behind and create a configuration file to handle the heavy lifting.

In your project’s root, create a webpack.config.js file:

touch webpack.config.js

This file can be as complicated as you make it. We’ll keep it light for the sake of this post:

// webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: 'dist' }, plugins: [ new HtmlWebpackPlugin({ title: 'Tree-shaking' }) ] }

This file provides webpack with the same information you gave to the CLI earlier. You’ve defined index.js as your entry file and bundle.js as your output file. You've also added your html-webpack-plugin which will generate an html file in your dist directory. Convenient.

Go ahead and test this to make sure it’s still working. Remove your dist directory, and in the command line type:

webpack

If everything went smoothly, you can open up dist/index.html and see "Hello World!".

Note: The use of a configuration file gives us the convenience of typing webpack instead of node_modules/.bin/webpack. Small wins.

Step 5: Babel

I mentioned earlier that webpack 2 brings native support for ES6 modules. This is all true, but it doesn’t change the fact that ES6 is not fully supported across all browsers. Because of this, you’re required to transform your ES6 code into readily acceptable JavaScript using a tool like Babel. In conjunction with webpack, Babel gives us the ability to write your “future JavaScript” without worrying about the implications of unsupported browsers.

Let’s go ahead and install Babel in your project:

npm i --save-dev babel-core babel-loader babel-preset-es2015

Take note of the babel-preset-es2015 package. This little guy is the reason I sat down to write all of this up.

Step 6: babel-loader

Webpack can be configured to transform specific files into modules via loaders. Once they are transformed, they are added to a dependency graph. Webpack uses the graph to resolve dependencies and includes only what is needed into the final bundle. This is the basis for how webpack works.

You can now configure webpack to use babel-loader to transform all of your .js files:

// webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: 'dist' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options: { presets: [ 'es2015' ] } } ] }, plugins: [ new HtmlWebpackPlugin({ title: 'Tree-shaking' }) ] };

The module property provides a set of instructions for webpack. It says, "take any files ending in .js and transform them using babel-loader, but don't transform any files inside of node_modules!"

We’re also passing the babel-preset-es2015 package as an option to babel-loader. This just tells babel-loaderhow to transform the JavaScript.

Run webpack again to make sure everything is good. Yes? Great! What we've done is bundled up your JavaScript files while compiling them down to JavaScript thats readily supported across browsers.

The underlying problem

The package babel-preset-es2015 contains another package named babel-plugin-transform-es2015-modules-commonjs that turns all of your ES6 modules into CommonJS modules. This isn't ideal, and here's why.

Javascript bundlers such as webpack and Rollup can only perform tree-shaking on modules that have a static structure. If a module is static, then the bundler can determine its structure at build time, safely removing code that isn’t being imported anywhere.

CommonJS modules do not have a static structure. Because of this, webpack won’t be able to tree-shake unused code from the final bundle. Luckily, Babel has alleviated this issue by providing developers with an option that you can pass to your presets array along with babel-preset-es2015:

options: { presets: [ [ 'es2015', { modules: false } ] ] }

According to Babel’s documentation:

“modules - Enable transformation of ES6 module syntax to another module type (Enabled by default to "commonjs"). Can be false to not transform modules, or one of ["amd", "umd", "systemjs", "commonjs"]".

Slide that extra bit of code into your configuration and you’ll be cooking with peanut oil.

The final state of webpack.config.js looks like this:

// webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: 'dist' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options: { presets: [ [ 'es2015', { modules: false } ] ] } } ] }, plugins: [ new HtmlWebpackPlugin({ title: 'Tree-shaking' }) ] };

The Grand Finale

Run webpack again and pop open your bundle.js file. You won't notice any difference. Before you go crazy, know this! It's ok. We've been running webpack in development mode this whole time. Webpack knows that you have unused exports in your code. Even though it's included in the final bundle, sayBye will never make it to production.

If you still don’t believe me, run webpack -p in your terminal. The -p option stands for production. Webpack will perform a few extra performance optimizations, including minification, removing any unused code along the way.

Open up bundle.js. Since it's minified, go ahead and search for Hello. It should be there. Search for Bye. It shouldn't.

Воила! Сада имате функционалну имплементацију подрхтавања дрвета у вебпацк-у 2!

За знатижељнике, полако сам понављао своју лагану конфигурацију вебпацка у ГитХуб Репо-у:

јаке-виес / вебпацк-рингла

вебпацк-рингла - Вебпацк котловница за личне пројекте

гитхуб.цом

Није замишљено да будете претерано опширни и надути. Усредсређен је на то да буде приступачан образац са упутствима на сваком кораку. Ако сте заинтересовани, погледајте!

Ако имате било каквих питања, слободно се обратите на Твиттер!