[译]Webpack 2和模板打包的初学者指南(上)

Webpack是模块打包工具。css

Webpack已成为现代Web开发最重要的工具之一。首先,它是一个JavaScript模板打包工具,他能转换全部的前端资源,如HTML和CSS,甚至图片。它可让你更好地控制你应用程序的HTTP请求数量,并容许你使用其余的风格资源(如Jade,Sass和ES6)。Webpack还容许你轻松地从npm上使用软件包。html

本文面向刚刚接触Webpack的初学者,主要介绍Webpack的初始设置和配置、模板、加载程序、插件、代码拆分和热模块替换。若是你发现视频教程对你更有帮助,我强烈推荐Glen Maddern’s的Webpack from First Principles做为一个起点,了解是什么使得Webpack那么特别。前端

接下来,你须要有Node.js installed环境,你也能够 download the demo app from our Github reponode

Setup

让咱们用npm新建一个项目并初始化,安装Webpack:webpack

mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack@beta --save-dev
mkdir src
touch index.html src/app.js webpack.config.js

编辑这些文件:git

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello webpack</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="dist/bundle.js"></script>
  </body>
</html>
// src/app.js
const root = document.querySelector('#root')
root.innerHTML = `<p>Hello webpack.</p>`
// webpack.config.js
const webpack = require('webpack')
const path = require('path')

const config = {
  context: path.resolve(__dirname, 'src'),
  entry: './app.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      include: path.resolve(__dirname, 'src'),
      use: [{
        loader: 'babel-loader',
        options: {
          presets: [
            ['es2015', { modules: false }]
          ]
        }
      }]
    }]
  }
}

module.exports = config

上面的配置是一个常见的起点,它指示webpack将咱们的入口点src/app.js编译输出到/dist/bundle.js中,全部的.js文件将经过BabelES2015转换到ES5github

为了让它运行,咱们须要安装三个包:babel-coreWebpack模块和资源转换器——babel-loader和预设的babel-preset-es2015
{ modules: false }启用Tree Shaking把咱们包中不被使用的输出删除,从而下降文件大小。web

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

最后,将package.json文件中的script部分替换为:npm

"scripts": {
  "start": "webpack --watch",
  "build": "webpack -p"
},

在命令行中运行npm start来监视模式启动webpack——每当咱们src目录中的.js文件更改时,都会从新编译输出到bundle中。控制台中的输出会告诉咱们正在建立的包,重要的是要注意包的数量和大小。
图片描述
如今你应该能够在浏览器中加载index.html,并使用“Hello webpack”。json

open index.html

打开dist/bundle.js查看webpack作了什么,顶部是webpack的模板引导代码,底部是咱们的模板。也许你对这不会有很深入的印象,但若是你跟着进度学到了这里,你能够运用ES6 modulewebpack生产一个能在全部浏览器中运行的用于生产的包。

输入命令行Ctrl + C中止webpack,并运行npm run build用于在生产模式下编译咱们的包。

请注意,此时包的大小已经从2.16kB降低到585字节。
再查看一下dist/bundle.js,你会看到一个丑恶的代码,咱们的包已经压缩或丑化(uglify/minify),代码运行效果是同样的,但它并不符合最少字符须要。

Modules

开箱即用的webpack知道如何使用各类格式的JavaScript模块,最显著的两种是:

  • ES2015的import语句

  • CommonJS的require()语句

咱们能够经过安装lodash并从app.js导入它来测试一下:

npm install lodash --save
// src/app.js
import {groupBy} from 'lodash/collection'

const people = [{
  manager: 'Jen',
  name: 'Bob'
}, {
  manager: 'Jen',
  name: 'Sue'
}, {
  manager: 'Bob',
  name: 'Shirley'
}, {
  manager: 'Bob',
  name: 'Terrence'
}]
const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`

运行npm start启动webpack,刷新一下index.html页面,你能够看到按manager排序的人数组。

让咱们来把people数组移动到本身的people.js文件中:

// src/people.js
const people = [{
  manager: 'Jen',
  name: 'Bob'
}, {
  manager: 'Jen',
  name: 'Sue'
}, {
  manager: 'Bob',
  name: 'Shirley'
}, {
  manager: 'Bob',
  name: 'Terrence'
}]

export default people

咱们可使用相对路径简单地从app.js导入它。

// src/app.js
import {groupBy} from 'lodash/collection'
import people from './people'

const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`

注意:没有相对路径的导入,如lodash/collection是从npm安装到node_modules的模块,本身写的模块是须要加一个相对路径,如./people来告诉webpack区分好各个模块。

Loaders

咱们已经介绍了babel-loader——不少loders之一,经过配置用于告诉webpack当遇到不一样文件类型的import时要怎么作。你能够把过个loader整合在一块儿,咱们能够经过从JavaScript中导入Sass来很好地了解这是如何工做的。

Sass

这种转换涉及到三个独立的loadernode-sass库:

npm install css-loader style-loader sass-loader node-sass --save-dev

webpack.config.js中给咱们的.scss文件添加新的配置规则:

// webpack.config.js
rules: [{
  test: /\.scss$/,
  use: [
    'style-loader',
    'css-loader',
    'sass-loader'
  ]
}, {
  // ...
}]

注意:每次更改webpack.config.js中的任何规则时,都须要使用Ctrl+Cnpm start命令从新启动项目。

loader数组会以相反的顺序执行:

  • sass-loader 把Sass转换成CSS

  • css-loader 把CSS解析到JavaScript中,并分解全部的依赖关系

  • style-loader 把咱们的CSS输出到文档中的<style>标签中

你能够把它当作函数调用,一个loader的输出会做为input输入下一个。

styleLoader(cssLoader(sassLoader('source')))

让咱们来添加一个Sass源文件:

/* src/style.scss */
$bluegrey: #2B3A42;

pre {
  padding: 20px;
  background: $bluegrey;
  color: #dedede;
  text-shadow: 0 1px 1px rgba(#000, .5);
}

你如今能够从JavaScript中直接请求Sass,从app.js的头部引入:

// src/app.js
import './style.scss'

// ...

刷新一下index.html你就会看到刚添加的样式了。

CSS in JS

咱们刚刚从JavaScript中导入了Sass文件,做为一个模块。

打开dist/bundle.js文件并搜索“pre {。事实上,咱们的Sass已经被编译成一个CSS字符串,并保存为咱们的bundle中的一个模板。当咱们在JavaScript中导入此模板时,style-loader会将该字符串输出到嵌入的<style>标签中。

我知道你确定是在想,为何会这样?

我不会在这里深刻讨论这个话题,可是你能够从如下几个方面考虑:

  • 你可能但愿包含在项目中的JavaScript组件依赖于其余资源(HTML、CSS、Images、SVG)来正常运行,若是这些资源能够整合在一块儿,那么导入和使用就会容易不少。

  • 消除死代码:当JS代码不须要导入JS组件时,将再也不导入CSS,生成的bundle只会包含执行某些操做的代码。

  • CSS模块:CSS的全局命名空间使得开发者很难确信CSS的一个更改不会产生任何的反作用。CSS modules经过在默认状况下使CSS local和暴露在JavaScript下使用的惟一类名来改变这一问题。

  • 经过巧妙的方法打包/拆分代码,来较少HTTP请求数量。

Images

咱们可以看到的最后一个关于loader的例子是使用url-loader处理图片。

在标准的HTML文档中,当浏览器遇到一个<img>标签或background-image属性时会抓取图片。使用webpack,当遇到小图片的时候,你能够经过将图片源做为字符串存储在JavaScript中来优化小图片,这样,你预加载它们,浏览器就不用为了提取它们而发起单独的请求了。

npm install file-loader url-loader --save-dev

添加一个加载图片的规则:

// webpack.config.js
rules: [{
  test: /\.(png|jpg)$/,
  use: [{
    loader: 'url-loader',
    options: { limit: 10000 } // Convert images < 10k to base64 strings
  }]
}, {
  // ...
}]

从新运行项目:Ctrl + Cnpm start

使用下面命令下载test image

curl https://raw.githubusercontent.com/sitepoint-editors/webpack-demo/master/src/code.png --output src/code.png

你如今能够在app.js的头部导入图片源:

// src/app.js
import codeURL from './code.png'
const img = document.createElement('img')
img.src = codeURL
img.style.backgroundColor = "#2B3A42"
img.style.padding = "20px"
img.width = 32
document.body.appendChild(img)

// ...

这将包括一张图片,其中src属性包含图片自己的data URL:

<img src="data:image/png;base64,iVBO..." style="background: #2B3A42; padding: 20px" width="32">

此外,因为使用url()引用的css-loader图片也经过url-loader运行,这就好像直接在CSS中嵌入它们。

/* src/style.scss */
pre {
  background: $bluegrey url('code.png') no-repeat center center / 32px 32px;
}

编译成为:

pre {
    background: #2b3a42 url("data:image/png;base64,iVBO...") no-repeat scroll center center / 32px 32px;
}

Modules to Static Assets

你如今应该能够看到loders是如何帮助在资源间创建一个依赖关系树的,这是webpack首页上的图片展现:
图片描述

尽管JavaScript是入口点,但webpack注意到你的其余资源(如HTML、CSS和SVG)都具备各自的依赖关系——这些依赖关系是应该视为构建过程的一部分的。

做者:Mark Brown
原文连接:A Beginner’s Guide to Webpack 2 and Module Bundling

相关文章
相关标签/搜索