Webpack —— JavaScript應用模塊打包工具。javascript
Webpack 有四個核心概念:css
entry(入口)html
單入口——單頁面應用前端
多入口——多頁面應用java
output(輸出)node
path: 輸出路徑(必須是絕對路徑) path.resolvereact
filename: 輸出文件名webpack
loadersgit
編譯文件web
plugins(插件)
webpack 功能擴展
Node.js 是 javascript的服務器版本,Webpack 在執行打包壓縮時是依賴 Node.js 的。
//分別導出一個或幾個變量(函數)
export let a = 1;
export const b = 2;
export function fn(){
console.log('fn')
}
//導出一個對象
let a = 1;
const b = 2;
function fn(){
console.log('fn')
}
export { a, b, fn };
//導出默認成員——僅能導出一個,默認引入的就是這一個
export default let a = 1;
複製代碼
//引入全部成員(as —— 給引入的值重命名)
import * as name from 'xxx';
//引入 default 成員
import a from 'xxx';
//只引入:引入 css 或 函數
import 'xxx';
//異步引入
let a =import("./util");
複製代碼
npm init
npm i webpack webpack-cli --save-dev
複製代碼
初始化項目,並安裝 Webpack 依賴,安裝 webpack-cli 才能在命令行運行 webpack 命令。
建立並配置 webpack.config.js
src
文件夾,新建 index.js
文件。index.js 文件:
console.log('index')
複製代碼
webpack.config.js 文件
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.min.js'
}
}
複製代碼
src
文件夾,新建 index.js
及 home.js
文件。index.js 文件:
console.log('index')
複製代碼
home.js 文件:
console.log('home')
複製代碼
webpack.config.js 文件
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
home: './src/home.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].min.js' //name爲對應入口文件的文件名
}
}
複製代碼
配置 package.json 文件,驗證基本配置
script
屬性:"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
複製代碼
npm run build
執行 webpack
命令,驗證輸入輸出配置。dist
文件夾,裏面有對應的文件生成。在 index.html 中引入打包好的 js 文件
方式一:手動引入
新建 index.html,並直接手動引入 js 文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script src='./dist/index.min.js'></script>
<script src='./dist/home.min.js'></script>
</html>
複製代碼
打開 index.html,即已成功引入編譯好的 index.min.js 及 home.min.js,執行裏面的代碼。
前面已經可使用 webpack ,但開發過程當中,每次都要手動引用 js 文件,更改代碼後還要從新編譯是很麻煩的,因此咱們接下來看下 webpack 的 plugins,來便於開發。
可經過插件html-webpack-plugin
,由指定的 html
模板生成新的 html
文件,並自動引入所需 js
等內容。
1)執行 npm i html-webpack-plugin --save-dev
命令,安裝依賴。
2)新建 index.ejs
文件
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
</body>
</html>
複製代碼
3)修改 webpack.config.js
的配置:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
home: './src/home.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].min.js' //name爲對應入口文件的文件名
},
plugins: [
new HtmlWebpackPlugin({
// 打包輸出HTML
title: 'New HTML', //打包後生成 html 的 title
minify: {
// 壓縮 HTML 文件
removeComments: true, // 移除 HTML 中的註釋
collapseWhitespace: true, // 刪除空白符與換行符
minifyCSS: true // 壓縮內聯 css
},
filename: 'index.html', // 生成後的文件名
template: 'index.ejs' // 根據此模版生成 HTML 文件
})
]
}
複製代碼
4)從新運行 npm run build
,生成新的 dist
包,包內會生成一個新的 index.html
文件,並自動引入了 index.min.js
文件。
<!DOCTYPE html><html><head><meta http-equiv="Content-type" content="text/html; charset=utf-8"><title>New HTML</title></head><body><div id="root"></div><script type="text/javascript" src="index.min.js"></script><script type="text/javascript" src="home.min.js"></script></body></html>
複製代碼
再次打包時需刪除舊文件
修改 webpack.config.js
,將輸出的 index.html
文件名改成其餘的,如 indexNew.html
npm run build
,生成的
dist
內文件列表以下:
index.html
還在,這裏可使用插件
clean-webpack-plugin
來刪除
webpack.config.js
中
output.path
目錄中的全部文件。
運行 npm install clean-webpack-plugin --save-dev
安裝依賴。
修改 webpack.config.js
配置。
npm run build
,生成的
dist
內文件列表以下:
indexNew.html
文件已被刪除。
npm i open-browser-webpack-plugin webpack-dev-server --save-dev
修改 webpack.config.js
配置以下:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動打開瀏覽器
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
home: './src/home.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].min.js' //name爲對應入口文件的文件名
},
plugins: [
new HtmlWebpackPlugin({
// 打包輸出HTML
title: 'New HTML', //打包後生成 html 的 title
minify: {
// 壓縮 HTML 文件
removeComments: true, // 移除 HTML 中的註釋
collapseWhitespace: true, // 刪除空白符與換行符
minifyCSS: true // 壓縮內聯 css
},
filename: 'index.html', // 生成後的文件名
template: 'index.ejs' // 根據此模版生成 HTML 文件
}),
// 默認狀況下,此插件將刪除 webpack output.path目錄中的全部文件。
new CleanWebpackPlugin(),
new OpenBrowserPlugin({ url: 'http://localhost:8080' })
]
}
複製代碼
修改 package.json
,添加 start
,使得運行 npm run start
可直接執行 webpack-dev-server
命令。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server",
"build": "webpack"
},
複製代碼
執行 npm run start
:
1)瀏覽器會自動打開 http://localhost:8080
;
2)修改 index.js
文件,保存文件,瀏覽器會自動刷新,更新內容。
代碼通過編譯、打包後,與源代碼已有很大差別,不便於調試。
source-map 會解決這個問題,生成 .map 文件,便於錯誤定位調試。
開啓方法:在 webpack.config.js 文件中添加一行配置:devtool: "source-map"
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動打開瀏覽器
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
home: './src/home.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].min.js' //name爲對應入口文件的文件名
},
plugins: [
new HtmlWebpackPlugin({
// 打包輸出HTML
title: 'New HTML', //打包後生成 html 的 title
minify: {
// 壓縮 HTML 文件
removeComments: true, // 移除 HTML 中的註釋
collapseWhitespace: true, // 刪除空白符與換行符
minifyCSS: true // 壓縮內聯 css
},
filename: 'index.html', // 生成後的文件名
template: 'index.ejs' // 根據此模版生成 HTML 文件
}),
// 默認狀況下,此插件將刪除 webpack output.path目錄中的全部文件。
new CleanWebpackPlugin(),
new OpenBrowserPlugin({ url: 'http://localhost:8080' })
],
//編譯前文件調試
devtool: "source-map"
}
複製代碼
如上,便可。可經過打印等方式進行測試。
loader ——文件編譯。
Babel 是一個 JavaScript 編譯器,Webpack 使用 babel-loader 來編譯 ES6。
此處咱們要建立一個 React 項目,因此同時也要添加 React 的相關依賴即配置。
yarn add babel babel-core babel-loader@7.1.2 babel-preset-env babel-preset-react
注: 如今直接安裝 babel-core 和 babel-loader,安裝的版本不對應會報錯,因此我在安裝時指定了 babel-loader 的版本,避免這個問題。
修改 webpack.config.js 以下:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動打開瀏覽器
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
home: './src/home.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].min.js' //name爲對應入口文件的文件名
},
plugins: [
new HtmlWebpackPlugin({
// 打包輸出HTML
title: 'New HTML', //打包後生成 html 的 title
minify: {
// 壓縮 HTML 文件
removeComments: true, // 移除 HTML 中的註釋
collapseWhitespace: true, // 刪除空白符與換行符
minifyCSS: true // 壓縮內聯 css
},
filename: 'index.html', // 生成後的文件名
template: 'index.ejs' // 根據此模版生成 HTML 文件
}),
// 默認狀況下,此插件將刪除 webpack output.path目錄中的全部文件。
new CleanWebpackPlugin(),
new OpenBrowserPlugin({ url: 'http://localhost:8080' })
],
module: {
rules: [
{
test: /\.(js|jsx)$/i,
use: [{
loader: "babel-loader",
options: {
presets: ["env", "react"],
}
}],
exclude: /node_modules/
}
]
}
}
複製代碼
修改 index.js 及 home.js 文件爲 react 語法
home.js文件
import React, { Component } from 'react';
export default class Home extends Component {
render() {
return (
<div style={{backgroundColor: '#0f0'}}>
home page
</div>
);
}
}
複製代碼
index.js文件
import React from 'react';
import { render } from 'react-dom';
import Home from './home';
render(<Home/>, document.getElementById('root'));
複製代碼
此時,頁面效果以下:
如上,React 語法被成功編譯。
建立 index.css 文件
.container {
background-color: aquamarine
}
複製代碼
修改 home.js 文件以下:
import React, { Component } from "react";
import './index.css'
export default class Home extends Component {
render() {
return (
<div className="container">
home page
</div>
);
}
}
複製代碼
npm run start
從新啓動項目,項目會報錯以下:
npm i style-loader css-loader --save-dev
修改 webpack.config.js 配置以下:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動打開瀏覽器
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
home: './src/home.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].min.js' //name爲對應入口文件的文件名
},
plugins: [
new HtmlWebpackPlugin({
// 打包輸出HTML
title: 'New HTML', //打包後生成 html 的 title
minify: {
// 壓縮 HTML 文件
removeComments: true, // 移除 HTML 中的註釋
collapseWhitespace: true, // 刪除空白符與換行符
minifyCSS: true // 壓縮內聯 css
},
filename: 'index.html', // 生成後的文件名
template: 'index.ejs' // 根據此模版生成 HTML 文件
}),
// 默認狀況下,此插件將刪除 webpack output.path目錄中的全部文件。
new CleanWebpackPlugin(),
new OpenBrowserPlugin({ url: 'http://localhost:8080' })
],
module: {
rules: [
{
test: /\.(js|jsx)$/i,
use: [{
loader: "babel-loader",
options: {
presets: ["env", "react"],
}
}],
exclude: /node_modules/
},
{
test: /\.css$/i, // 針對 .css 後綴的文件設置 loader
use: ['style-loader', 'css-loader']
}
]
}
}
複製代碼
添加了針對 .css 文件的 loader,來對 .css 文件進行處理。
<style></style>
標籤,裏面是 css-loader 解析出的 css 樣式。建立 index.less 文件以下:
.container {
background-color: aquamarine
}
複製代碼
修改 home.js 文件以下:
import React, { Component } from "react";
import './index.less'
export default class Home extends Component {
render() {
return (
<div className="container">
home page
</div>
);
}
}
複製代碼
npm i less less-loader --save-dev
修改 webpack.config.js 配置,module/rules 下添加對於 less 文件的解析:
{
test: /\.less$/, // 針對 .less 後綴的文件設置 loader
use: ['style-loader', 'css-loader', 'less-loader']
}
複製代碼
從新啓動項目,less 文件生效,頁面效果以下:
autoprefixer 按照瀏覽器使用量決定須要添加哪些瀏覽器前綴,postcss-loader 按照 autoprefixer 的結果來添加瀏覽器前綴。
修改 index.less 文件以下:
.container {
background-color: aquamarine;
transform: rotate(0deg);
transition-duration: 1000ms;
}
.container:hover {
background-color: aquamarine;
transform: rotate(360deg)
}
複製代碼
npm i less postcss-loader autoprefixer --save-dev
修改 webpack.config.js 配置,給 css、less 文件添加 postcss-loader 的解析,
有兩種方式:
1)在 webpack.config.js 的 modele/rules 內指定 postcss-loader 的配置
{
test: /\.css$/, // 針對 .css 後綴的文件設置 loader
use: ['style-loader', 'css-loader', {
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')]
}
}]
},
{
test: /\.(less|css)$/, // 針對 .less 後綴的文件設置 loader
use: ['style-loader', 'css-loader', 'less-loader', {
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')]
}
}]
}
複製代碼
2)修改 webpack.config.js,並單首創建 postcss.config.js ,進行配置
修改webpack.config.js 文件,modele/rules 添加以下配置:
{
test: /\.css$/, // 針對 .css 後綴的文件設置 loader
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.(less|css)$/, // 針對 .less 後綴的文件設置 loader
use: ['style-loader', 'css-loader', 'less-loader', 'postcss-loader']
}
複製代碼
postcss.config.js 文件
module.exports = {
plugins: [require('autoprefixer')]
}
複製代碼
相對比而言,我更傾向於第一種,以避免建立太多的配置文件,形成混亂。
從新啓動項目,查看瀏覽器元素,樣式前綴已添加成功。
1)添加 .broserslistrc 文件,進行配置
last 3 version //支持每一個版本的最近三個版本
>2% //大於百分之二的用戶使用
複製代碼
2)無需建立新文件,直接在 package.json 文件內添加屬性進行配置
"browserslist": [
"last 5 version",
" >1%"
]
複製代碼
從新啓動,效果以下:
按照設置的規則從新對咱們的 css 樣式添加了前綴。
src 文件夾下建立 images 文件夾,並添加 bg.png 圖片
修改 index.less 文件以下:
.container {
width: 100%;
height: 600px;
background: url('./images/bg.png');
background-size: 100%;
background-repeat: no-repeat;
}
複製代碼
從新啓動項目,會報錯以下:
如上,須要配置對應的 loader 來解析圖片。
執行npm i file-loader --save-dev
,安裝依賴。
修改 webpack.config.js 配置, modole/rule 下添加配置以下:
{
test: /\.(png|jpg|jpeg|gif)$/i, // 針對 .png|.jpg|.jpeg | .gif 後綴的圖片設置 loader
use: [{
loader: 'file-loader',
options: {
outputPath: 'imgs/', //相對於 output.path 的輸出目錄
}
}]
}
複製代碼
重啓項目,則引入圖片成功,效果以下:
file-loader 能夠解析項目中的圖片引入,根據配置,將圖片輸出到相應路徑,並修改打包後文件中的引用路徑,使其指向打包後的文件。
針對圖片引用,url-loader 封裝了 file-loader。
增長了 limit 屬性,文件大小大於 limit 值,會調用 file-loader 進行處理;
文件大小小於 limit 值,會將文件轉爲 base64 格式,以減小文件請求次數。
安裝 url-loader 依賴
npm i url-loader --save-dev
修改 webpack.config.js 配置, modole/rule 下添加配置以下:
{
test: /\.(png|jpg|jpeg|gif)$/i, // 針對 .png|.jpg|.jpeg | .gif 後綴的圖片設置 loader
use: [{
loader: 'url-loader',
options: {
outputPath: 'imgs/', //相對於 output.path 的輸出目錄
limit: 8*1024 //大於此數值依舊用 file-loader處理,打包到 imgs 裏面,小於此數值的轉爲 base64,以減小文件請求次數
}
}]
}
複製代碼
重啓項目,圖片引用成功,執行 npm run build
,可發現,大於 8k 的圖片會被打包到 dist/imgs 文件夾內,小於 8k 的則不會被打包輸出,而是轉爲 base64 。
src 文件夾下一個字體文件——difital-7.ttf,這是一個液晶字體文件,修改 index.less 文件以下:
@font-face{
font-family: "digital";
src: url(./digital-7.ttf);
}
.container {
width: 100%;
height: 600px;
background: url('./images/bgimg.jpg');
background-size: 100%;
background-repeat: no-repeat;
font-family: "digital"
}
複製代碼
保存項目編譯後,會報錯以下:
同圖片,須要配置對應的 url-loader 來解文字片,修改 webpack.config.js 配置, modole/rule 下添加配置以下:
{
test: /\.(eot|svg|ttf|woff|woff2)$/i, // 針對 eot|svg|ttf|woff|woff2 後綴的字體設置 loader
use: [{
loader: 'url-loader',
options: {
outputPath: 'fonts/', //相對於 output.path 的輸出目錄
limit: 4*1024 //大於此數值依舊用 file-loader處理,打包到 fonts 裏面,小於此數值的轉爲 base64,以減小文件請求次數
}
}]
}
複製代碼
從新啓動項目,則字體引用成功,效果以下:
經過修改 limit 值,從新打包,可測試 limit 值設置是否有效。
上述區別須要經過兩個設置來實現。
在 webpack.config.js 中經過判斷 env 的值,來進行不一樣的配置
修改 package.json 來設置 process.env.NODE_ENV:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --env.development",
"build": "webpack --env.production",
"eslint": "eslint --init"
},
複製代碼
根目錄下新建 config 文件夾,並在下面新建 webpack.production.config 和 webpack.development.config 文件。
webpack.config.js 文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動打開瀏覽器
const path = require('path')
module.exports = function(env, argv) {
console.log('env', env)
env = env || { development: true }
return {
entry: {
index: './src/index.js',
},
module: {
rules: [
{
test: /\.(js|jsx)$/i,
use: [{
loader: "babel-loader",
options: {
presets: ["env", "react"],
}
}],
exclude: /node_modules/
},
{
test: /\.css$/i, // 針對 .css 後綴的文件設置 loader
use: ['style-loader', 'css-loader', {
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')]
}
}]
},
{
test: /\.(less|css)$/i, // 針對 .less 後綴的文件設置 loader
use: ['style-loader', 'css-loader', 'less-loader', {
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')]
}
}]
},
{
test: /\.(png|jpg|jpeg|gif)$/i, // 針對 .png|.jpg|.jpeg | .gif 後綴的圖片設置 loader
use: [{
loader: 'url-loader',
options: {
outputPath: 'imgs/', //相對於 output.path 的輸出目錄
limit: 8*1024 //大於此數值依舊用 file-loader處理,打包到 imgs 裏面,小於此數值的轉爲 base64,以減小文件請求次數
}
}]
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/i, // 針對 eot|svg|ttf|woff|woff2 後綴的字體設置 loader
use: [{
loader: 'url-loader',
options: {
outputPath: 'fonts/', //相對於 output.path 的輸出目錄
limit: 4*1024 //大於此數值依舊用 file-loader處理,打包到 fonts 裏面,小於此數值的轉爲 base64,以減小文件請求次數
}
}]
}
]
},
...env.production ? require('./config/webpack.production.config') : require('./config/webpack.development.config')
}
}
複製代碼
mode 有三種模式:
webpack.production.config 文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動打開瀏覽器
const path = require('path')
module.exports = {
mode: 'production',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.min.js' //name爲對應入口文件的文件名
},
plugins: [
new HtmlWebpackPlugin({
// 打包輸出HTML
title: 'New HTML', //打包後生成 html 的 title html模板時不生效
minify: {
// 壓縮 HTML 文件
removeComments: true, // 移除 HTML 中的註釋
collapseWhitespace: true, // 刪除空白符與換行符
minifyCSS: true // 壓縮內聯 css
},
filename: 'index.html', // 生成後的文件名
template: 'index.ejs' // 根據此模版生成 HTML 文件
}),
// 默認狀況下,此插件將刪除 webpack output.path目錄中的全部文件。
new CleanWebpackPlugin()
]
}
複製代碼
webpack.development.config 文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動打開瀏覽器
const path = require('path')
module.exports = {
mode: 'development',
output: {
filename: 'main.js' //name爲對應入口文件的文件名
},
//編譯前文件調試
devtool: "source-map",
plugins: [
new HtmlWebpackPlugin({
// 打包輸出HTML
title: 'New HTML', //打包後生成 html 的 title
minify: {
// 壓縮 HTML 文件
removeComments: true, // 移除 HTML 中的註釋
collapseWhitespace: true, // 刪除空白符與換行符
minifyCSS: true // 壓縮內聯 css
},
filename: 'index.html', // 生成後的文件名
template: 'index.ejs' // 根據此模版生成 HTML 文件
}),
new OpenBrowserPlugin({ url: 'http://localhost:8080' })
],
}複製代碼
歡迎關注個人公衆號-前端之階,即時獲取更多前端技術,還可獲取前端大羣,裏面不少知名互聯網前端朋友,前端技術更新太快,不能被落伍淘汰,共同窗習,共同進步!