[译] Webpack——令人困惑的处所

原文 Webpack—The Confusing Parts
issue议论

Webpack是如今基于React和Redux开辟的运用的重要打包东西。我想运用Angular 2或其他框架开辟的运用也有许多在运用Webpack。

当我第一次看到Webpack的设置文件时,它看起来异常的生疏,我异常的迷惑。经由一段时间的尝试今后我以为这是由于Webpack只是运用了比较迥殊的语法和引入了新的道理,因而会让运用者以为迷惑。这些也是致使Webpack不被人熟习的缘由。

由于刚最先运用Webpack很让人迷惑,我以为有必要写几篇引见Webpack的功用和特征的文章以协助初学者疾速明白。此文是最最先的一篇。

Webpack的中心道理

Webpack的两个最中心的道理离别是:

1. 统统皆模块

正如js文件可所以一个“模块(module)”一样,其他的(如css、image或html)文件也可视作模 块。因而,你能够require('myJSfile.js')亦能够require('myCSSfile.css')。这意味着我们能够将事物(营业)支解成更小的易于治理的片断,从而到达反复应用等的目标。

2. 按需加载

传统的模块打包东西(module bundlers)终究将一切的模块编译天生一个巨大的bundle.js文件。然则在实在的app里边,“bundle.js”文件能够有10M到15M之大能够会致使运用一向处于加载中状况。因而Webpack运用许多特征来支解代码然后天生多个“bundle”文件,而且异步加载部份代码以完成按需加载。

好了,下面来看看那些令人疑心的部份吧。

1. 开辟形式和临盆形式

起首要知道的是Webpack有许许多多的特征,一些是”开辟形式“下才有的,一些是”临盆形式“下才有的,另有一些是两种形式下都有的。

《[译] Webpack——令人困惑的处所》

平常运用到Webpack云云多特征的项目都邑有两个比较大的Webpack设置文件

为了天生bundles文件你能够在package.json文件到场以下的scripts项:

"scripts": {
  // 运转npm run build 来编译天生临盆形式下的bundles
  "build": "webpack --config webpack.config.prod.js",
  // 运转npm run dev来天生开辟形式下的bundles以及启动当地server
  "dev": "webpack-dev-server"
 }

2. webpack CLI 和webpack-dev-server

值得注重的是,Webpack作为模块打包东西,供应两种用户交互接口:

  1. Webpack CLI tool:默许的交互体式格局(已随Webpack本身装置到当地)

  2. webpack-dev-server:一个Node.js服务器(须要开辟者从npm自行装置)

Webpack CLI(有利于临盆形式下打包)

这类体式格局能够从敕令行猎取参数也能够从设置文件(默许叫webpack.config.js)猎取,将猎取到的参数传入Webpack来打包。

固然你也能够从敕令行(CLI)最先进修Webpack,今后你能够重要在临盆形式下运用到它。

用法:

体式格局1: 
// 全局形式装置webpack
npm install webpack --g
// 在终端输入
$ webpack // <--运用webpack.config.js天生bundle

体式格局 2 :
// 费全局形式装置webpack然后增加到package.json依靠里边
npm install webpack --save
// 增加build敕令到package.json的scripts设置项
"scripts": {
 "build": "webpack --config webpack.config.prod.js -p",
 ...
 }
// 用法:
"npm run build"
webpack-dev-server(有利于在开辟形式下编译)

这是一个基于Express.js框架开辟的web server,默许监听8080端口。server内部挪用Webpack,如许做的优点是供应了分外的功用如热更新“Live Reload”以及热替代“Hot Module Replacement”(即HMR)。

用法:

体式格局 1:
// 全局装置
npm install webpack-dev-server --save
// 终端输入
$ webpack-dev-server --inline --hot

用法 2:
// 增加到package.json scripts
"scripts": {
 "start": "webpack-dev-server --inline --hot",
 ...
 }
// 运转: 
$ npm start

// 浏览器预览:
http://localhost:8080
Webpack VS Webpack-dev-server选项

注重像inlinehot这些选项是Webpack-dev-server特有的,而别的的如hide-modules则是CLI形式特有的选项。

webpack-dev-server CLI选项和设置项

别的值得注重的是你能够经由过程以下两种体式格局向webpack-dev-server传入参数:

  1. 经由过程webpack.config.js文件的”devServer”对象

  2. 经由过程CLI选项

// 经由过程CLI传参
webpack-dev-server --hot --inline
// 经由过程webpack.config.js传参
devServer: {
  inline: true,
  hot:true
}

我发明偶然devServer设置项(hot: true 和inline: true)不见效,我更倾向运用以下的体式格局向CLI通报参数:

// package.json
{
    "scripts": "webpack-dev-server --hot --inline"
}

注重:肯定你没有同时传入hot:true-hot

webpack-dev-server的“hot” 和 “inline”选项

“inline”选项会为进口页面增加“热加载”功用,“hot”选项则开启“热替代(Hot Module Reloading)”,即尝试从新加载组件转变的部份(而不是从新加载全部页面)。假如两个参数都传入,当资本转变时,webpack-dev-server将会先尝试HRM(即热替代),假如失利则从新加载全部进口页面。

// 当资本发作转变,以下三种体式格局都邑天生新的bundle,然则又有区分:
 
// 1. 不会革新浏览器
$ webpack-dev-server
//2. 革新浏览器
$ webpack-dev-server --inline
//3. 从新加载转变的部份,HRM失利则革新页面
$ webpack-dev-server  --inline --hot

3. “entry”:值离别是字符串、数组和对象的状况

Enter设置项通知Webpack运用的根模块或肇端点在那里,它的值可所以字符串、数组或对象。这看起来能够令人疑心,由于差别范例的值有着差别的目标。

像绝大多数app一样,倘使你的运用只要一个单一的进口,enter项的值你能够运用恣意范例,终究输出的效果都是一样的。

《[译] Webpack——令人困惑的处所》

enter:数组范例

然则,假如你想增加多个相互不相互依靠的文件,你能够运用数组花样的值。

比方,你能够在html文件里援用了“googleAnalytics.js”文件,能够通知Webpack将其加到bundle.js的末了。

《[译] Webpack——令人困惑的处所》

enter:对象

如今,假定你的运用是多页面的(multi-page application)而不是SPA,有多个html文件(index.html和profile.html)。然后你经由过程一个对象通知Webpack为每个html天生一个bundle文件。

以下的设置将会天生两个js文件:indexEntry.js和profileEntry.js离别会在index.html和profile.html中被援用。

《[译] Webpack——令人困惑的处所》

用法:

//profile.html
<script src=”dist/profileEntry.js”></script>
//index.html
<script src=”dist/indexEntry.js”></script>

注重:文件名取自“entry”对象的键名。

enter:夹杂范例

你也能够在enter对象里运用数组范例,例以下面的设置将会天生3个文件:vender.js(包括三个文件),index.js和profile.js文件。

《[译] Webpack——令人困惑的处所》

4. output:“path”项和“publicPath”项

output项通知webpack怎样存储输出效果以及存储到那里。output的两个设置项“path”和“publicPath”能够会形成疑心。

“path”仅仅通知Webpack效果存储在那里,但是“publicPath”项则被许多Webpack的插件用于在临盆形式下更新内嵌到css、html文件里的url值。

《[译] Webpack——令人困惑的处所》

比方,在localhost(译者注:即当地开辟形式)里的css文件中边你能够用“./test.png”如许的url来加载图片,然则在临盆形式下“test.png”文件能够会定位到CDN上而且你的Node.js服务器多是运转在HeroKu上边的。这就意味着在临盆环境你必需手动更新一切文件里的url为CDN的途径。

但是你也能够运用Webpack的“publicPath”选项和一些插件来在临盆形式下编译输出文件时自动更新这些url。

《[译] Webpack——令人困惑的处所》

// 开辟环境:Server和图片都是在localhost(域名)下
.image { 
  background-image: url('./test.png');
 }
// 临盆环境:Server布置下HeroKu然则图片在CDN上
.image { 
  background-image: url('https://someCDN/test.png');
 }

5. 模块加载和链式模块加载

模块加载器是可自在增加的Node模块,用于将差别范例的文件“load”或“import”并转换成浏览器能够辨认的范例,如js、Stylesheet等。更高等的模块加载器以至能够支撑运用ES6里边的“require”或“import”引入模块。

比方,你能够运用babel-loader来将运用ES6语法写成的文件转换成ES5:

module: {
 loaders: [{
  test: /\.js$/, // 婚配.js文件,假如经由过程则运用下面的loader
  exclude: /node_modules/, // 消除node_modules文件夹
  loader: 'babel' // 运用babel(babel-loader的简写)作为loader
 }]
链式(管道式)的加载器(从右往左实行)

多个loader能够用在同一个文件上而且被链式挪用。链式挪用时从右到左实行且loader之间用“!”来支解。

比方,假定我们有一个名为“myCssFile.css”的css文件,然后我们想将它的内容运用style标签内联到终究输出的html里边。我们能够运用css-loader和style-loader两个loader来到达目标。

module: {
 loaders: [{
  test: /\.css$/,
  loader: 'style!css' //(short for style-loader!css-loader)
 }]

这里展现它是怎样事情的:

《[译] Webpack——令人困惑的处所》

  1. Webpack在模块颞部搜刮在css的依靠项,即Webpack搜检js文件是不是有“require(‘myCssFile.css’)”的援用,假如它发明有css的依靠,Webpack将css文件交给“css-loader”去处置惩罚

  2. css-loader加载一切的css文件以及css本身的依靠(如,@import 其他css)到JSON对象里,Webpack然后将处置惩罚效果传给“style-loader”

  3. style-loader接收JSON值然后增加一个style标签并将其内嵌到html文件里

6. loader本身能够设置

模块加载器(loader)本身能够依据传入差别的参数举行设置。

鄙人面的例子中,我们能够设置url-loader来将小于1024字节的图片运用DataUrl替代而大于1024字节的图片运用url,我们能够用以下两种体式格局经由过程传入“limit“参数来完成这一目标:

《[译] Webpack——令人困惑的处所》

7. .babelrc 文件

babal-loader运用”presets“设置项来标识怎样将ES6语法转成ES5以及怎样转换React的JSX成js文件。我们能够用以下的体式格局运用”query“参数传入设置:

module: {
  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /(node_modules|bower_components)/,
      loader: 'babel',
      query: {
        presets: ['react', 'es2015']
      }
    }
  ]
}

但是在许多项目里babal的设置能够比较大,因而你能够把babal-loader的设置项零丁保存在一个名为”.babelrc“的文件中,在实行时babal-loader将会自动加载.babelrc文件。

所以在许多例子里,你能够会看到:

//webpack.config.js 
module: {
  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /(node_modules|bower_components)/,
      loader: 'babel'
    }
  ]
}

//.bablerc
{
 presets: ['react', 'es2015']
}

8. 插件

插件平常都是用于输出bundle的node模块。

比方,uglifyJSPlugin猎取bundle.js然后紧缩和殽杂内容以减小文件体积。

相似的extract-text-webpack-plugin内部运用css-loader和style-loader来网络一切的css到一个处所终究将效果提取效果到一个自力的”styles.css“文件,而且在html里边援用style.css文件。

//webpack.config.js
// 猎取一切的.css文件,兼并它们的内容然后提取css内容到一个自力的”styles.css“里
var ETP = require("extract-text-webpack-plugin");

module: {
 loaders: [
  {test: /\.css$/, loader:ETP.extract("style-loader","css-loader") }
  ]
},
plugins: [
    new ExtractTextPlugin("styles.css") //Extract to styles.css file
  ]
}

注重:假如你只是想把css运用style标签内联到html里,你没必要运用extract-text-webpack-plugin,仅仅运用css loader和style loader即可:

module: {
 loaders: [{
  test: /\.css$/,
  loader: 'style!css' // (short for style-loader!css-loader)
 }]

9. 加载器(loader)和插件

你能够已认识到了,Loader处置惩罚零丁的文件级别而且平常作用于包天生之前或天生的过程当中。

而插件则是处置惩罚包(bundle)或许chunk级别,且平常是bundle天生的末了阶段。一些插件如commonschunkplugin以至更直接修正bundle的天生体式格局。

10. 处置惩罚文件的扩展名

许多Webpack的设置文件都有一个resolve属性,然后就像下面代码所示有一个空字符串的值。空字符串在此是为了resolve一些在import文件时不带文件扩展名的表达式,如require('./myJSFile')或许import myJSFile from './myJSFile'(译者注:现实就是自动增加后缀,默许是当做js文件来查找途径)

{
 resolve: {
   extensions: ['', '.js', '.jsx']
 }
}

就这么多。

    原文作者:dmyang
    原文地址: https://segmentfault.com/a/1190000005089993
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞