咱們經過一個簡單的例子來理解webpack的工做,首先,咱們初始化一個項目,css
npm init
複製代碼
而後,安裝webpack和webpack-clihtml
npm install webpack webpack-cli --save-dev
複製代碼
而後,創建兩個文件前端
src/component.jsvue
export default (text = "Hello world") => {
const element = document.createElement("div");
element.innerHTML = text;
return element;
};
複製代碼
src/index.jsnode
import component from "./component";
document.body.appendChild(component());
複製代碼
終端輸入:react
node_modules/.bin/webpack
複製代碼
終端輸出:webpack
Hash: 24db01e09460251a2e2d
Version: webpack 4.20.2
Time: 99ms
Built at: 2018-10-04 16:43:58
Asset Size Chunks Chunk Names
main.js 1.04 KiB 0 [emitted] main
Entrypoint main = main.js
[0] ./src/index.js + 1 modules 236 bytes {0} [built]
| ./src/index.js 78 bytes [built]
| ./src/component.js 158 bytes [built]
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to'production' for
this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each
environment.You can also set it to 'none' to disable any default behavior. Learn
more: https://webpack.js.org/concepts/mode/
複製代碼
這時候終端的信息告訴咱們打包已經成功,hash、version、time、build日期、靜態資源明細等,而後就是一個warning表示須要一個mode,是開發環境仍是生產環境。es6
若是終端輸入:web
node_modules/.bin/webpack --mode development
複製代碼
終端輸出:正則表達式
Hash: fbb6656fe339f2629619
Version: webpack 4.20.2
Time: 98ms
Built at: 2018-10-04 21:33:53
Asset Size Chunks Chunk Names
main.js 4.64 KiB main [emitted] main
Entrypoint main = main.js
[./src/component.js] 158 bytes {main} [built]
[./src/index.js] 78 bytes {main} [built]
複製代碼
這時候由於傳入了設置了mode因此沒有了warning。
固然webapp是須要html的,同時須要在瀏覽器中調試的。
安裝html-webpack-plugin
npm install html-webpack-plugin --save-dev
複製代碼
webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
plugins: [
new HtmlWebpackPlugin({
title: "Webpack demo",
}),
],
};
複製代碼
終端輸入:
Hash: 0b26f05922ba70d8a92d
Version: webpack 4.20.2
Time: 392ms
Built at: 2018-10-04 22:28:30
Asset Size Chunks Chunk Names
main.js 1.04 KiB 0 [emitted] main
index.html 181 bytes [emitted]
Entrypoint main = main.js
[0] ./src/index.js + 1 modules 236 bytes {0} [built]
| ./src/index.js 78 bytes [built]
| ./src/component.js 158 bytes [built]
Child html-webpack-plugin for "index.html":
1 asset
Entrypoint undefined = index.html
[2] (webpack)/buildin/global.js 509 bytes {0} [built]
[3] (webpack)/buildin/module.js 519 bytes {0} [built]
+ 2 hidden modules
複製代碼
與以前的相比多了html的信息,dist文件夾也多了index,html文件。
構建快捷方式:
package.json
"scripts": {
"build": "webpack --mode production"
},
複製代碼
經過終端輸入:
npm run build
複製代碼
其輸出結果和上面的同樣。
打包一個簡單的文件,須要的準備。
寫稍微複雜一點的app都須要單獨創建,webpack.config.js來管理webpack的配置
HtmlWebpackPlugin能夠生成HTML做爲你app的入口
用package.json scripts來管理webpack。你能夠用它做爲一個輕量級的發任務啓動器和使用webpack以外的功能等。
經過webpack-cli webpack提供了命令行,在沒有配置的狀況下你也可使用webpack,可是還有不少高級的配置須要你配置。
webpack的watch模式與webpack-dev-server
經過命令行:
npm run build -- --watch
複製代碼
這時候會處於watch狀態下,當源文件發生修改的,dist中相應的文件也會發生改變,這與以前沒修改一次就須要從新打包不同。
與watch模式相比,webpack-dev-server不只有監視模式並且功能更增強大。
webpack-dev-server根據字面意思就能夠理解,這裏既有dev又有server,咱們能夠理解它是運行在‘在開發環境下內存中的服務器’,咱們能夠進一步理解,當咱們的代碼發生變化時,這些改變不會編譯到打包文件中,這個過程有利於咱們開發和調試。並且webpack-dev-server更是支持了Hot Module Replacement (HMR)這個功能使得咱們在改變代碼的時候無須刷新整個頁面。
安裝WDS
npm install webpack-dev-server --save-dev
複製代碼
要將WDS集成到項目中,首先,咱們須要將寫好咱們的npm 腳本,咱們通常約定爲npm start:
"scripts": {
"start": "webpack-dev-server --mode development"
"build": "webpack --mode production"
},
複製代碼
咱們經過npm start 開啓服務
> one@1.0.0 start /Users/jiangyiling/study/webpack-demo/one
> webpack-dev-server --mode development
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wdm」: Hash: 7b54b098d32e9acb0067
Version: webpack 4.20.2
Time: 569ms
Built at: 2018-10-04 23:19:55
Asset Size Chunks Chunk Names
main.js 342 KiB main [emitted] main
index.html 181 bytes [emitted]
Entrypoint main = main.js
[./node_modules/_ansi-html@0.0.7@ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/_ansi-regex@2.1.1@ansi-regex/index.js] 135 bytes {main} [built]
[./node_modules/_events@1.1.1@events/events.js] 8.13 KiB {main} [built]
[./node_modules/_loglevel@1.6.1@loglevel/lib/loglevel.js] 7.68 KiB {main} [built]
[./node_modules/_strip-ansi@3.0.1@strip-ansi/index.js] 161 bytes {main} [built]
[0] multi ./node_modules/_webpack-dev-server@3.1.9@webpack-dev-server/client?http://localhost:8080 ./src 40 bytes {main} [built]
[./node_modules/_querystring-es3@0.2.1@querystring-es3/index.js] 127 bytes {main} [built]
[./node_modules/_url@0.11.0@url/url.js] 22.8 KiB {main} [built]
[./node_modules/_webpack-dev-server@3.1.9@webpack-dev-server/client/index.js?http://localhost:8080] ./node_modules/_webpack-dev-server@3.1.9@webpack-dev-server/client?http://localhost:8080 7.78 KiB {main} [built]
[./node_modules/_webpack-dev-server@3.1.9@webpack-dev-server/client/overlay.js] 3.58 KiB {main} [built]
[./node_modules/_webpack-dev-server@3.1.9@webpack-dev-server/client/socket.js] 1.05 KiB {main} [built]
[./node_modules/_webpack@4.20.2@webpack/hot/emitter.js] (webpack)/hot/emitter.js 77 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] ./node_modules/webpack/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./src/component.js] 160 bytes {main} [built]
[./src/index.js] 78 bytes {main} [built]
+ 12 hidden modules
Child html-webpack-plugin for "index.html":
1 asset
Entrypoint undefined = index.html
[./node_modules/_html-webpack-plugin@3.2.0@html-webpack-plugin/lib/loader.js!./node_modules/_html-webpack-plugin@3.2.0@html-webpack-plugin/default_index.ejs] 392 bytes {0} [built]
[./node_modules/_lodash@4.17.11@lodash/lodash.js] 527 KiB {0} [built]
[./node_modules/_webpack@4.20.2@webpack/buildin/global.js] (webpack)/buildin/global.js 509 bytes {0} [built]
[./node_modules/_webpack@4.20.2@webpack/buildin/module.js] (webpack)/buildin/module.js 519 bytes {0} [built]
ℹ 「wdm」: Compiled successfully.
複製代碼
經過終端的輸出,咱們能夠看到一些信息,這個項目的地址在
localhost:8080
複製代碼
這時你修改代碼會發現,終端輸出信息會增長,頁面的內容也會發生改變,這邊是熱更新了。
在咱們的實際項目中,WDS在其中起着重要的做用,因此它的配置也並非咱們上面的demo那麼簡單,咱們須要給它配置各類參數,雖然你能夠經過腳手架工具來設置,可是這顯然是不方便的,因此咱們繼續經過例子來學習吧。
webpack.config.js
...
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// WDS配置內容
devServer: {
// Display only errors to reduce the amount of output.
stats: "errors-only",
// Parse host and port from env to allow customization.
//
// If you use Docker, Vagrant or Cloud9, set
// host: options.host || "0.0.0.0";
//
// 0.0.0.0 is available to all network devices
// unlike default `localhost`.
host: process.env.HOST, // Defaults to `localhost`
port: process.env.PORT, // Defaults to 8080
open: true, // Open the page in browser
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack demo",
}),
],
};
複製代碼
經過上面的配置文件咱們能夠發現,與上一章相比咱們多了一個devServer對象。這個對象的內容咱們逐一解釋,
stats
"errors-only"表示只有在錯誤時才展現錯誤內容
host
host的默認值是localhost
port
port的默認值是8080
open
表示運行了WDS便自動在瀏覽器中打開
咱們能夠根據須要設置這些參數,例如:
咱們經過命令行工具修改port
PORT=3000 npm start
複製代碼
咱們也能夠在webpack.config.js中直接指定端口號
'''
port:3000
'''
複製代碼
這時,咱們打開頁面就是localhost:3000了。
固然WDS還有其餘的一些屬性,咱們回憶一下,咱們在使用vue和react的咱們是否是有遇到過這種狀況呢。
webpack.config.js
module.exports = {
devServer: {
...
overlay: true,
},
...
}
複製代碼
咱們在開發的時候,修改項目中的資源會實現刷新的功能,可是咱們修改webpack的配置呢,結果天然是頁面並不會刷新。怎樣作可讓咱們在修改webpack配置時也實現刷新呢。
npm install nodemon --save-dev
複製代碼
package.json
"scripts": {
"start": "nodemon --watch webpack.config.js --exec \"webpack-dev-server --mode development\"",
"build": "webpack --mode production"
},
複製代碼
這主要是在低版本的操做系統中使用,這裏不表。
WDS還有一些實用的功能,好比:代理等功能。
咱們查看vue、react等腳手架工具生成的項目會發現,它們並無把全部功能模塊寫在同一個文件中,咱們在配置一個webpack時主要是按功能和不一樣的環境進行配置的,好比開發環境和生產環境,各自都有一些特別的設置,因此咱們須要將webpack文件進行配置,作到模塊化,這樣不只讓文件結構更清晰,也更有利於維護。
如同前端的各類框架同樣,有一個重要思想是把項目模塊化,顆粒度更細。webpack也同樣。咱們將webpack配置顆粒化了,咱們怎麼將他們鏈接起來呢。
Object.assign 和 Array.concat分別能夠將對象和數組組合,Object.assign的使用會存在覆蓋的狀況,因此webpack-merge將這兩個方法給組合了起來,而且對這兩種方法進行了必定的優化。具體的感覺,以下圖:
> merge = require("webpack-merge")
...
> merge(
... { a: [1], b: 5, c: 20 },
... { a: [2], b: 10, d: 421 }
... )
{ a: [ 1, 2 ], b: 10, c: 20, d: 421 }
複製代碼
將webpack-merge放到項目中
npm install webpack-merge --save-dev
複製代碼
根據以前的內容咱們將,webpack.config.js進一步的抽象
webpack.parts.js
exports.devServer = ({ host, port } = {}) => ({
devServer: {
stats: "errors-only",
host, // Defaults to `localhost`
port, // Defaults to 8080
open: true,
overlay: true,
},
});
複製代碼
webpack.config.js
const merge = require("webpack-merge");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const parts = require("./webpack.parts");
const commonConfig = merge([
{
plugins: [
new HtmlWebpackPlugin({
title: "Webpack demo",
}),
],
},
]);
const productionConfig = merge([]);
const developmentConfig = merge([
parts.devServer({
// Customize host/port here if needed
host: process.env.HOST,
port: process.env.PORT,
}),
]);
module.exports = mode => {
if (mode === "production") {
return merge(commonConfig, productionConfig, { mode });
}
return merge(commonConfig, developmentConfig, { mode });
};
複製代碼
從上面的配置咱們能夠看出咱們將webpack分爲了兩個環境,production和development。而且把development環境須要使用的devServer抽離出來作了一個單獨的文件,還有公用的html插件那一部分也作成了一個單獨的對象。
咱們怎樣來識別何時使用不一樣的環境呢,固然咱們須要繼續修改npm腳本。
package.json
"scripts": {
"start": "webpack-dev-server --env development",
"build": "webpack --env production"
// "start": "webpack-dev-server --mode development",
// "build": "webpack --mode production"
},
複製代碼
--env既能夠給傳字符串也能夠傳對象,下面例子很簡潔的說明這個問題:
package.json
"scripts": {
"start": "webpack-dev-server --env development",
"build": "webpack --env.target production"
},
複製代碼
這時候配置接收到參數字符串development和對象{target:production}。
這一章主要講述的是css樣式的加載,從js代碼中抽離css已結剝離沒有使用過得css
加載樣式須要css-loader和style-loader。
css-loader能夠經過@import和url()去查找匹配的文件,相似於es2015的import,將css樣式引入到js中。
style-loader經過標籤將css樣式注入到html中。
開始,安裝css-loader和style-loader:
npm install css-loader style-loader --save-dev
複製代碼
而後在webpack配置文件夾中配置
webpack.parts.js
exports.loadCSS = ({ include, exclude } = {}) => ({
module: {
rules: [
{
test: /\.css$/,
include,
exclude,
use: ["style-loader", "css-loader"],
},
],
},
});
複製代碼
webpack.config.js
const commonConfig = merge([
...
parts.loadCSS(),
]);
複製代碼
從上面中的代碼能夠清楚的認識到css-loader和style-loader的用法,loader是將源文件加載而後輸出新的文件,並且他們是從右至左加載,
use: ["style-loader", "css-loader"],
複製代碼
能夠理解是
styeLoader(cssLoader(input))
複製代碼
首先安裝less-loader
npm install less-loader less --save-d
複製代碼
webpack.parts.js
exports.loadCSS = ({ include, exclude } = {}) => ({
module: {
rules: [
{
test: /\.less$/,
include,
exclude,
use: ["style-loader","css-loader","less-loader"],
},
],
},
});
複製代碼
處理方式相似於咱們上面的css文件,相似的預處理器還有sass,stylus等。
瞭解css-loader和style-loader的做用.
webpack能夠處理各類css預處理器,例如:less、sass和stylus等
ps:這一章還有不少內容能夠進一步探討
複製代碼
在咱們上一章提到的css樣式都是注入到js代碼中的,這顯然不知足咱們的要求,咱們確定是但願把css分離出來。因此,咱們須要用MiniCssExtractPlugin來解決這個問題,因爲它會帶來編譯時的開銷,因此,這個須要咱們把它用在生產環境中。
npm install mini-css-extract-plugin --save-dev
複製代碼
webpack.parts.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
exports.extractCSS = ({ include, exclude, use = [] }) => {
// Output extracted CSS to a file
const plugin = new MiniCssExtractPlugin({
filename: "[name].css",
});
return {
module: {
rules: [
{
test: /\.less$/,
include,
exclude,
use: [
MiniCssExtractPlugin.loader,
].concat(use),
},
],
},
plugins: [plugin],
};
};
複製代碼
webpack.config.js
const merge = require("webpack-merge");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const parts = require("./webpack.parts");
const commonConfig = merge([
{
plugins: [
new HtmlWebpackPlugin({
title: "Webpack demo",
}),
],
},
]);
const productionConfig = merge([
parts.extractCSS({use:[ "css-loader"]})
]);
const developmentConfig = merge([
parts.devServer({
// Customize host/port here if needed
host: process.env.HOST,
port: process.env.PORT,
}),
parts.loadCSS()
]);
module.exports = mode => {
console.log('mode',mode)
if (mode === "production") {
return merge(commonConfig, productionConfig, { mode });
}
return merge(commonConfig, developmentConfig, { mode });
};
複製代碼
經過這樣設置咱們即可以在開發環境中使用HMR在生產環境中使用css分離,在使用了css分離加載事後,css文件會自動注入html中。
像之前咱們使用的Bootstrap庫,在使用它的時候有不少多餘的樣式並無用上,打包的時候能刪除沒有用的樣式,對打包的體積會有明顯的縮小。
PurifyCSS是一個經過分析文件來實現這一目標的工具。它遍歷代碼並肯定正在使用的CSS類,有足夠的信息能夠從項目中刪除未使用的CSS。
安裝purify-css及相關:
npm install glob purifycss-webpack purify-css --save-dev
複製代碼
webpack配置:
webpack.parts.js
const PurifyCSSPlugin = require("purifycss-webpack");
exports.purifyCSS = ({ paths }) => ({
plugins: [new PurifyCSSPlugin({ paths })],
});
複製代碼
將PurifyCSSPlugin插件與webpack配置鏈接,PurifyCSSPlugin須要在MiniCssExtractPlugin後面使用:
webpack.config.js
...
const path = require("path");
const glob = require("glob");
const parts = require("./webpack.parts");
const PATHS = {
app: path.join(__dirname, "src"),
};
...
const productionConfig = merge([
...
parts.purifyCSS({
paths: glob.sync(`${PATHS.app}/**/*.js`, { nodir: true }),
}),
]);
複製代碼
glob.sync(${PATHS.app}/**/*.js
, { nodir: true }) 返回組件js文件的絕對路徑數組。
打包事後的css樣式是刪除了沒有用的css,體積也變得小了。
不一樣的瀏覽器對一些特殊的css屬性須要特定的前綴,爲了兼容全部的瀏覽器,咱們須要給這些特殊的css屬性加上前綴,可是,一個一個的屬性加前綴是一個很繁瑣的過程,因此咱們須要在編譯過程用插件自動加上這些前綴。
實現Autoprefixing須要安裝postcss-loader和autoprefixer
npm install postcss-loader autoprefixer --save-dev
複製代碼
設置webpack:
webpack.parts.js
exports.autoprefix = () => ({
loader: "postcss-loader",
options: {
plugins: () => [require("autoprefixer")()],
},
});
複製代碼
而後鏈接webpack配置:
webpack.config.js
const productionConfig = merge([
parts.extractCSS({
use: ["css-loader", parts.autoprefix()],
}),
...
]);
複製代碼
咱們還須要選擇咱們想要支持的瀏覽器,因此咱們須要建一個文件.browserslistrc
,在這個文件中定義須要支持的瀏覽器。好比:
.browserslistrc
> 1% # Browser usage over 1%
Last 2 versions # Or last two versions
IE 8 # Or IE 8
複製代碼
autoprefix不只能夠添加前綴並且能夠根據browserslistrc來刪除前綴。
autoprefix的做用不言而喻,這大大的減小了咱們的工做量。
webpack提供了不少方法來設置模塊loader,webpack 2 引進了use字段簡化了操做,而且在loader中使用的是絕對路徑,這有利於webpack在不一樣的環境下使用。
webpack支持各類各樣的加載器,它也支持一些開箱即用的js庫,你須要設置loader來讀取你文件的結構。
下面是一個babel的例子:
webpack.config.js
module.exports = {
...
module: {
rules: [
{
test: /\.js$/,
include: path.join(__dirname, "app"),
exclude(path) {
// You can perform more complicated checks as well.
return path.match(/node_modules/);
},
use: "babel-loader",
},
],
},
};
複製代碼
loader執行的順序是從左到右,從下至上的。
能夠設置特定的loader在上面提到的常規規則的前面或者後面執行,能夠經過pre
或者post
來規定設置的loader在其餘的loader的前面或者後面執行。
{
test: /\.js$/,
include: PATHS.app,
use: "babel-loader?presets[]=env",
},
複製代碼
USE
使用function時{
test: /\.js$/,
include: PATHS.app,
use: (data)=>{
return {
loader:"babel-loader"
}
},
},
複製代碼
其中參數包括resource
、realResource
、resourceQuery
、issuer
、compiler
。
雖然這種方式並不受推崇,可是它確實也是一種方式: src/index.js
import "style-loader!css-loader!./pure.css";
複製代碼
這種把loader直接寫到import裏,而且不一樣的loader之間用!
隔開。
test
經過include
和exclude
來匹配文件,下面詳細討論:
test
能夠是一個正則表達式、函數、字符串、對象和數組。
include
同上
exclude
同上
resource
匹配條件是路徑中含有規定的查詢的資源,例如:
`resource:/inline/`
所匹配的文件的路徑中須要像這樣
/path/foo.inline.js, /path/bar.png?inline
複製代碼
issuer
匹配條件是路在規定的文件中引用的資源,例如:
`issuer: /bar.js/`
若是/path/foo.png這個資源在/path/bar.js中被引用了,那麼這個文件將會被匹配上。
複製代碼
resourcePath
匹配條件是上面提到的resource
的子集,例如:
`resource:/inline/`
所匹配的文件的路徑中須要像這樣
/path/foo.inline.js
複製代碼
resourceQuery
匹配條件是上面提到的resource
的子集,例如:
`resource:/inline/`
所匹配的文件的路徑中須要像這樣
/path/bar.png?inline
複製代碼
Boolean值也能夠進一步限制匹配條件:
not
and
or
這三個條件就如同字面意思自行理解。
oneOf
字段能夠用於loader匹配具體的靜態資源,例如:
{
test: /\.png$/,
oneOf: [
{
resourceQuery: /inline/,
use: "url-loader",
},
{
resourceQuery: /external/,
use: "file-loader",
},
],
},
複製代碼
若是上下文信息是存在於文件中的而不是存在query(查詢)的,則使用resourcePath
而不是resourceQuery
。
issuer可用於資源引入到規定的文件中的匹配,例如:
{
test: /\.css$/,
rules: [
{
issuer: /\.js$/,
use: "style-loader",
},
{
use: "css-loader",
},
],
},
複製代碼
這裏是指,只匹配在js文件中引用的css資源。
混合issuer
和not
{
test: /\.css$/,
rules: [
{
issuer: { not: /\.css$/ },
use: "style-loader",
},
{
use: "css-loader",
},
],
}
複製代碼
這裏不匹配在css中引用的css資源。
loader-runner容許您在沒有webpack的狀況下單獨運行它們,inspect-loader
容許檢查loader之間內容的傳遞,你能夠經過這個插件瞭解到資源流的詳情。
webpack能夠經過url-loader加載行內資源。這個加載器能夠將圖片轉成base64
的格式,這個過程將比較大的靜態資源變小了,並且能夠減小服務器請求次數。
當靜態資源經過url-loader時,若是文件大小大於了url-loader設置的大小則調用file-loader,返回路徑,url-loader內置file-loader。
由於url-loader內置file-loader,因此,url-loader是一個很好的選擇,能夠不用考慮文件的大小。以下:
{
test: /\.(jpg|png)$/,
use: {
loader: "url-loader",
options: {
limit: 25000,
name: "[path][name].[hash].[ext]"
//name:"./static/image/[name].[hash].[ext]"
},
},
},
複製代碼
從代碼中能夠知道對靜態資源限制是25k,可是當文件的體積大於25K會調用file-loader,並且,將原文件按照[path][name].[hash].[ext]
的格式打包,正如註釋的咱們也能夠按照本身想要的樣子輸出。
webpack容許幾種方式加載svg,但仍是相似引入圖片的方式仍是最方便的,以下:
{
test: /\.svg$/,
use: "file-loader",
},
複製代碼
固然還有不少方式,這裏不一一贅述。
能夠經過image-webpack-loader
、svgo-loader
和imagemin-webpack-plugin
這些loader應該第一時間處理數據,所以這些Loader在use字段值的末尾。壓縮文件是頗有價值的至少能減小帶寬。
resize-image-loader
和responsive-loader
能夠設置圖片的srcset屬性。
這個技術可讓多個小圖片合成一張圖片,這個技術能夠用於生成動畫,同時還避免了請求的開銷。
webpack-spritesmith
能夠將提供的圖片轉化爲sprite sheet
和Sass/Less/Stylus mixins
。至於細節,在這裏不贅述了。
image-trace-loader
在加載圖片並將結果暴露出來做image/svg+xml
URL編碼數據,它能夠與url-loader
和file-loader
一塊兒使用,在圖片正在加載的時候,顯示佔位符。
lqip-loader
也有相同的做用,與tracing不一樣的是,這個loader是提供一個模糊的圖片。
image-size-loader
能夠提供image的尺寸、類型、體積等。
在樣式文件中,可使用@import
和url()
引入,css-loader
同樣,也能夠在代碼中引入。
若是使用Image和css-loader都選擇了sourceMap
,那麼output.publicPath
設置爲絕對路徑指向服務器很是重要。
url-loader
能夠設置option參數將把指定大小圖片寫成base64編碼的,體積超過了就調用file-loader
。file-loader
打包圖片可返回其路徑並寫入代碼中,並對其進行相關的命名。sourceMap
須要設置絕對路徑output.publicPath
。字體加載和圖片加載很類似,加載字體的方式有不少,能夠據需使用url-loader
和file-loader
像圖片同樣。
.woff2 被現代服務器廣爲採用,Loader設置和加載圖像一致,以下:
{
test: /\.woff$/,
use: {
loader: "url-loader",
options: {
limit: 50000,
},
},
},
複製代碼
在世紀的開發過程當中確定須要更多的設置,以下:
{
test:/\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
use:{
loader:'url-loader',
options: {
limit: 5000,
mimetype: "application/font-woff",
name: "./static/fonts/[name].[ext]",
}
}
}
複製代碼
考慮到對全部服務器的支持,咱們通常會選擇傳入多種格式的字體,因此webpack須要對不一樣格式的文件進行解析。
{
test: /\.(ttf|eot|woff|woff2)$/,
use: {
loader: "file-loader",
options: {
name: "fonts/[name].[ext]",
},
},
},
複製代碼
在css文件中:
@font-face {
font-family: "myfontfamily";
src: url("./fonts/myfontfile.woff2") format("woff2"),
url("./fonts/myfontfile.woff") format("woff"),
url("./fonts/myfontfile.eot") format("embedded-opentype"),
url("./fonts/myfontfile.ttf") format("truetype");
/* Add other formats as you see fit */
}
複製代碼
file-loader容許修改具體的輸出,這和圖片輸出相似,此外,操做publicPath
並覆蓋默認的loader設置,下面的設置能夠解決這個問題。 (待續...)
{
// Match woff2 and patterns like .woff?v=1.1.1.
test: /\.woff2?(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: "url-loader",
options: {
limit: 50000,
mimetype: "application/font-woff",
name: "./fonts/[name].[ext]", // Output below ./fonts
publicPath: "../", // Take the directory into account
},
},
},
複製代碼
咱們知道爲了兼容低版本的瀏覽器咱們須要把高版本的es6代碼轉成較低版本的代碼,例如:es5裏就沒有const聲明,這個代碼就不能在低版本瀏覽器中運行。這時候就須要用babel來處理了。
babel在現階段幾乎是必須的,開發者能夠經過babel-loader
使用babel
和webpack
。
安裝:
npm install babel-loader @babel/core --save-dev
複製代碼
webpack.parts.js
exports.babelloader = () =>{
return {
module: {
rules: [
{
test: /\.js$/,
include: path.join(__dirname, "./src"),
exclude(path) {
// You can perform more complicated checks as well.
return path.match(/node_modules/);
},
use:{
loader: "babel-loader",
options: {
presets: ['latest']
}
}
},
],
},
}
}
複製代碼
webpack.config.js
const commonConfig = merge([
...
parts.loadJavaScript({ include: PATHS.app }),
]);
複製代碼
作完這些配置還須要配置一個.babelrc
文件,這個文件是用來。
.babelrc
這個文件是用來配置babel轉碼的規則和插件的,例如咱們配置的:
{
"presets": ['latest']
}
複製代碼
這時候再調用
npm run build -- --devtool false --mode development
複製代碼
以前的es6都會被轉碼成es5
當代碼被打包事後,調試會變得比較麻煩。如何定位拋出錯誤的位置,Source maps
的出現就是來解決這個問題的。
Source Maps
和分離Source Maps
webpack能夠生成兩種形式的一種是內聯Source Maps
另外一種是分離Source Maps
,內聯和分離相比之下,內聯主要是用在開發環境下,它具備更好的性能,而分離的則更適合生產環境,由於它的體積更小。
Source Maps
webpack提供了兩種方式使用Source Maps
,可使用devtool
字段,再者使用plugins
這個在後面會討論到。
Source Maps
直接使用webpack的devtool
字段,以下:
webpack.parts.js
exports.generateSourceMaps = ({ type }) => ({
devtool: type,
});
複製代碼
webpack支持不少source map
類型,這些不一樣主要是基於其質量和不一樣的構建速度。如今,能夠測試一下默認設置下的開發,以下:
webpack.config.js
const productionConfig = merge([
parts.generateSourceMaps({ type: "source-map" }),
...
]);
複製代碼
webpack支持的Source map
類型能夠分爲兩種策略:
inline主要是用於開發環境下,而Separate用於生產環境下,若是不在意性能開銷在開發環境下也可使用Separate。
webpack提供多種inline source map類型,一般eval
是起點,當在chrome和firefox中時,推薦cheap-module-eval-source-map
做爲速度和質量的妥協。source-map
的類型不少,在這裏很少作介紹了。
(這一章內容太繁瑣了,後面再更新)
生產環境下的js文件是一個單文件,若是應用發生了變化,那麼客戶端須要把文件從新下載下來。
只下載改變的那一部分是最好的,Bundle splitting
能夠經過optimization.splitChunks.cacheGroups
實現。
npm install react react-dom --save
複製代碼
src/index.js
import "react";
import "react-dom";
...
複製代碼
打包事後會發現,打包出來的體積比較大。
在
(待續。。。)