閱讀目錄

webpack簡(jiǎn)述

按照webapck官網(wǎng)所說,webpack是一個(gè)模塊打包工具(webpack is a module bundler)。它接收依賴的模塊,將其轉(zhuǎn)化為靜態(tài)資源。

webpack與眾不同的三大核心概念

  1. Code Spliting

  2. Loaders

  3. Plugin System

配置(configuration)

CLI

如果使用CLI,webpack將會(huì)讀取webpack.config.js文件(或者通過--config選項(xiàng)傳遞的文件),這個(gè)文件需要暴露這樣的配置對(duì)象:

module.exports = {    // configuration};

常見CLI option

1)開發(fā)環(huán)境簡(jiǎn)寫 -d

等價(jià)于:--debug --devtool source-map --output-pathinfo

2)生產(chǎn)環(huán)境簡(jiǎn)寫 -p

等價(jià)于:--optimize-minimize --optimize-occurrence-order

3)監(jiān)視模式 --watch

4)配置文件 --config example.config.js

指定新的配置文件,而不是默認(rèn)的webpack.config.js

5)常見的顯示選項(xiàng)

  • --progress

  • --display-chunks

  • --display-reasons

  • --display-error-details

  • --display-modules

  • --display-exclude

可以通過script來定義腳本,然后npm run 命令名。

一個(gè)簡(jiǎn)單的配置對(duì)象,注意不是json,只是簡(jiǎn)單的object

{    context: __dirname + "/app",    entry: "./entry",    output: {        path: __dirname + "/dist",        filename: "bundle.js"
    }
}

context

context:根目錄(絕對(duì)路徑!)。可以認(rèn)為是文件查找的上下文。默認(rèn)process.cwd()

entry

entry:包的入口點(diǎn),有三種形式

  1. 一個(gè)string

  2. 一個(gè)由多個(gè)string構(gòu)成的array

  3. 一個(gè)object(多頁(yè)面場(chǎng)景下),key是chunk的name,value可以是string或者array

output

output.filename

不要在這里指定絕對(duì)路徑

多入口情況下使用占位符

  • [name] 模塊名稱

  • [hash] 模塊編譯后的(整體)Hash值

  • [chunkhash] 分片的Hash值,可以認(rèn)為是文件的版本號(hào),也可以認(rèn)為是文件的MD5值,在靜態(tài)資源的版本管理中非常有用

output.path

output.publicPath

指定 public URL地址,當(dāng)我們要將output的文件放在不同的域名或者CDN上時(shí)十分有用

module

module.loaders 一個(gè)自動(dòng)應(yīng)用的loaders的數(shù)組,每項(xiàng)(item)可以有這些屬性:

  • test: A condition that must be met

  • exclude: A condition that must not be met

  • include: An array of paths or files where the imported files will be transformed by the loader

  • loader: A string of “!” separated loaders

  • loaders: An array of loaders as string

resolve

resolve.alias

模塊別名定義,方便后續(xù)直接引用別名

resolve: {    alias: { AppStore : 'js/stores/AppStores.js',//之后直接 require('AppStore')
    } 
}

resolve.root

包含你模塊的目錄(絕對(duì)路徑),也可以是一個(gè)目錄數(shù)組,這個(gè)設(shè)置應(yīng)該被用于添加個(gè)人目錄到webpack查找路徑里

必須是個(gè)絕對(duì)路徑,不要這樣寫./app/modules

resolve.modulesDirectories

這是一個(gè)目錄數(shù)組,用來解析到當(dāng)前目錄以及祖先目錄和查找模塊。這個(gè)函數(shù)的工作原理和node如何查找node_modules目錄很像。比如如果值為["mydir"],webpack會(huì)查找“./mydir”, “../mydir”, “../../mydir”等等

默認(rèn): ["web_modules", "node_modules"]

resolve.extensions

一個(gè)用來解析模塊的拓展名數(shù)組。比如,為了發(fā)現(xiàn)一個(gè)CoffeeScript文件,你的數(shù)組里應(yīng)該包含字符串".coffee"

默認(rèn): ["", ".webpack.js", ".web.js", ".js"]

注意:設(shè)置這個(gè)選項(xiàng)將會(huì)重寫默認(rèn)值

externals

指定不該被webpack打包的模塊,但是在打包后的包中仍然保留了請(qǐng)求。

我們可以通過它來暴露全局變量,而在需要的文件中直接require或import就可以了

externals: {  jquery: 'jQuery'}

plugins

給編譯器添加額外的插件

各種loaders

webpack 可以使用 loader 來預(yù)處理文件。這允許你打包除 JavaScript 之外的任何靜態(tài)資源。你可以使用 Node.js 來很簡(jiǎn)單地編寫自己的 loader。

loader的使用有三種方法,分別是:

  • 在require中顯式指定,即上面看到的用法

  • 在配置項(xiàng)(webpack.config.js)中指定

  • 在命令行中指定

1)babel-loader

轉(zhuǎn)換ES6語(yǔ)法或React語(yǔ)法

通過presets選擇ES6特性,也可以在package.json中指定

解決babel-loader處理React的preset問題:npm i --save-dev babel-preset-react

2)css相關(guān)

  • style-loader 將模塊的導(dǎo)出作為樣式添加到DOM中

  • css-loader 解析CSS文件后,使用import加載,并且返回CSS代碼,可以在loader后面?modules以支持CSS Module

  • less-loader 加載和轉(zhuǎn)譯LESS文件

  • sass-loader 加載和轉(zhuǎn)譯SASS/SCSS文件,須先安裝node-sass,windows可能安裝出錯(cuò),使用cnpm i node-sass --save-dev或者如下:
    npm install --save-dev node-sass --registry=https://registry.npm.taobao.org --disturl=https://npm.taobao.org/dist --sass-binary-site=http://npm.taobao.org/mirrors/node-sass

  • postcss-loader 使用PostCSS加載和轉(zhuǎn)譯CSS/SSS文件,可以進(jìn)行autoprefixer

CSS中@import另一個(gè)CSS怎么處理?(非SASS、LESS)

給css-loader添加參數(shù)

loader: 'style-loader!css-loader?importLoaders=1!postcss-loader'

3)模板相關(guān)

  • html-loader 導(dǎo)出HTML為字符串,需要引用靜態(tài)資源

  • jade-loader 加載Jade模板并返回一個(gè)函數(shù)

  • markdown-loader 將Markdown轉(zhuǎn)譯為HTML

  • handlebars-loader 將Handlebars轉(zhuǎn)換為HTML

  • ejs-loader 將underscore模板轉(zhuǎn)換為HTML

4)圖片相關(guān)

  • file-loader

  • url-loader 與file-loader,但如果文件小于限制,可以返回 data URL

  • image-loader 壓縮圖片

components模板引用相對(duì)路徑圖片不會(huì)替換?

可以使用絕對(duì)路徑或者這樣寫src="${require('../../assets/bg.png')}"

5)bundle-loader

bundle-loader是一個(gè)用來在運(yùn)行時(shí)異步加載模塊的loader。可以用來做代碼分割

6)exports-loader

可以從模塊中導(dǎo)出變量。

在實(shí)際使用中,用exports-loader最多的場(chǎng)景是將某些不支持模塊化規(guī)范的模塊所聲明的全局變量作為模塊內(nèi)容導(dǎo)出。
如下可以導(dǎo)出全局變量Hello,exports-loader還可以支持同時(shí)導(dǎo)出多個(gè)變量,例如exports?HELLO,WORLD

module.exports = {    module:{
        loaders:[
            { test: require.resolve('./hello'), loader: "exports?Hello" }
        ]
    }
};

7)imports-loaders

用于向一個(gè)模塊的作用域內(nèi)注入變量(Can be used to inject variables into the scope of a module)

8)expose-loader

把一個(gè)模塊導(dǎo)出并付給一個(gè)全局變量

require("expose?libraryName!./file.js");// Exposes the exports for file.js to the global context on property "libraryName".// In web browsers, window.libraryName is then available.

各種plugins

1)HtmlWebpackPlugin

參數(shù):

  • template html模板地址,默認(rèn)為webpack.config.js所在的目錄

  • inject 插入位置

  • title

  • date等

2)CommonsChunkPlugin

將多個(gè)入口起點(diǎn)之間共享的公共模塊,生成為一些 chunk,并且分離到單獨(dú)的 bundle 中,例如,1vendor.bundle.js 和 app.bundle.js

3)ExtractTextWebpackPlugin

從 bundle 中提取文本(CSS)到分離的文件(app.bundle.css)

4)ProvidePlugin

ProvidePlugin可以將模塊作為一個(gè)變量,被webpack在其他每個(gè)模塊中引用。只有你需要使用此變量的時(shí)候,這個(gè)模塊才會(huì)被 require進(jìn)來。多數(shù)之前遺留的模塊,會(huì)依賴于已存在的某些特定全局變量,比如jQuery插件中的$或者jQuery。在這種場(chǎng)景,你可以在每次遇到全局標(biāo)識(shí)符$的時(shí)候,在webpack中預(yù)先設(shè)置var $ = require(“jquery”)。

module.exports = {
  plugins: [    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery'
    })
  ]
};

Environment flags

windows下使用cross-env的npm包兼容處理,可以在package.json設(shè)置如下:

"scripts": {    "clear": "rm -rf build&& mkdir build",    "start": "npm run clear&& cross-env NODE_ENV=development webpack-dev-server --host 0.0.0.0 --devtool eval --progress --color --profile",    "deploy": "npm run clear&& cross-env NODE_ENV=production webpack -p --progress"}

webpack.config.js

var isProduction = process.env.NODE_ENV === 'production';

plugins: [new webpack.DefinePlugin({    'process.env': {        'NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
    }
})]

Code splitting(代碼分割)

使用require.ensure

// main.jsrequire.ensure(['./a'], function(require) {  var content = require('./a');  document.open();  document.write('<h1>' + content + '</h1>');  document.close();
});// a.jsmodule.exports = 'Hello World';

require.ensure告訴Webpack,./a.js應(yīng)該從bundle.js分離并且打包成一個(gè)單獨(dú)的文件

注意require.ensure只會(huì)加載模塊而不會(huì)去解析

也可以用bundle-loader進(jìn)行代碼分割

// main.js// Now a.js is requested, it will be bundled into another filevar load = require('bundle-loader!./a.js');// To wait until a.js is available (and get the exports)//  you need to async wait for it.load(function(file) {  document.open();  document.write('<h1>' + file + '</h1>');  document.close();
});

vendor chunk

可以用CommonsChunkPlugin插件將公共庫(kù)(vendor)打包成一個(gè)單獨(dú)的文件

var webpack = require('webpack');module.exports = {
  entry: {
    app: './main.js',
    vendor: ['jquery'],
  },
  output: {
    filename: 'bundle.js'
  },
  plugins: [    new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.js')
  ]
};

模塊熱替換(Hot Module Replacement)

npm i webpack-dev-server --save-dev

配置

主要參考資料

webpack官方文檔

阮一峰webpack教程

標(biāo)簽: webpack

http://www.cnblogs.com/ang-/p/6599348.html