webpack4.x深入與實踐
一、什麼是webpack
是一個前端資源載入/打包工具。它將根據模組的依賴關係進行靜態分析,然後將這些模組按照指定的規則生成對應的靜態資源。它做的事情是,分析你的專案結構,找到JavaScript模組以及其它的一些瀏覽器不能直接執行的拓展語言(Scss,TypeScript等),並將其轉換和打包為合適的格式供瀏覽器使用。可以將多種靜態資源 js、css、less 轉換成一個靜態檔案,減少了頁面的請求。
二、安裝和命令列
1、新建一個目錄,進入目錄,初始化
2、安裝
全域性安裝
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText $ npm install webpack -g
在輸出版本時,顯示,要安裝webpack-cli
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText $ webpack -v The CLI moved into a separate package: webpack-cli. Please install 'webpack-cli' in addition to webpack itself to use the CLI. -> When using npm: npm install webpack-cli -D -> When using yarn: yarn add webpack-cli -D
$ npm install webpack-cli -g
這樣就能輸出版本,可以看到我安裝的是4.2.0,這裡要注意,自webpack4之後,使用有很大的變化
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack -v
4.2.0
區域性安裝
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ cnpm install webpack webpack-cli --save-dev
(1)練習(坑):處理js檔案,在專案根目錄下,新建hello.js,然後打包
$ webpack hello.js hello.bundle.js
Hash: e4a6ea308e8987e8d082
Version: webpack 4.2.0
Time: 556ms
Built at: 2018-3-27 11:35:19
1 asset
Entrypoint main = main.js
[0] ./hello.js 40 bytes {0} [built]
[1] multi ./hello.js hello.bundle.js 40 bytes {0} [built]
WARNING in configuration
The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment.
ERROR in multi ./hello.js hello.bundle.js
Module not found: Error: Can't resolve 'hello.bundle.js' in 'E:\workspace\xampp\htdocs\text\webpackText'
@ multi ./hello.js hello.bundle.js
顯示沒有配置webpack的mode選項,預設有production和development兩種,我們輸入
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development
Hash: f28182541f5f8d1a0d8e
Version: webpack 4.2.0
Time: 62ms
Built at: 2018-3-27 11:42:01
ERROR in Entry module not found: Error: Can't resolve './src' in 'E:\workspace\xampp\htdocs\text\webpackText'
依然有錯:未找到入口模組發成錯誤,
這是因為webpack4.x是以專案根目錄下的./src/index.js作為入口,所以我們要新建src目錄且改hello.js為index.js
這裡還要注意:
webpack4.x的打包已經不能用webpack 檔案a 檔案b
的方式,而是直接執行webpack --mode development
或者webpack --mode production
,這樣便會預設進行打包,入口檔案是'./src/index.js'
,輸出路徑是'./dist/main.js'
,其中src目錄即index.js檔案需要手動建立,而dist目錄及main.js會自動生成。
因此我們不再按webpack 檔案a 檔案b
的方式執行webpack指令,而是直接執行
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development
Hash: 34a98f4253e13bf8f430
Version: webpack 4.2.0
Time: 108ms
Built at: 2018-3-27 11:47:52
Asset Size Chunks Chunk Names
main.js 2.85 KiB main [emitted] main
Entrypoint main = main.js
[./src/index.js] 40 bytes {main} [built]
這樣便能實現打包。
每次這樣寫是不是都點麻煩,我們可以在package.json中
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development"
},
每次執行就可以:
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ npm run dev // == webpack --mode development
(2)練習:處理css檔案
新建一個css檔案style.css,在index.js中引入
然後打包:
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development
ERROR in ./src/style.css
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type.
會報如上錯誤,是因為webpack不支援css檔案型別,需要依賴loader
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ npm install css-loader style-loader --save-dev
css-loader:使webpack可以處理css檔案
style-loader:新建一個style標籤,把css-loader處理過的檔案放進去,然後插入到HTML標籤中
安裝之後使用(直接在檔案前):或者(在命令列):
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development --module-bind 'css=style-loader!css-loader' // 給css繫結。。。。
那每次更新都要執行一次,有沒有自動更新的???
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development --module-bind 'css=style-loader!css-loader' --watch // watch引數監聽,每次儲存檔案會自動執行
(3)其他引數:
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/webpackText
$ webpack --mode development --module-bind 'css=style-loader!css-loader' --progress --display-modules --display-reasons
--progerss:會出現打包過程,有百分比進度條
--display-modules:會把所有打包的模組列出來
--display-reasons:會把打包的原因列出來
三、webpack的配置
(1)新建一個專案並初始化
[email protected] MINGW64 /
$ cd e:/workspace/xampp/htdocs/text/demo/webpack-demo
$ npm init
$ cnpm install webpack webpack-cli --save-dev
(2)新建一個檔案webpack.config.js(預設名),是在使用webpack時預設的配置檔案
單檔案輸入:
const path = require('path');
module.exports = {
entry: './src/js/main.js', // 入口檔案
output: { // 出口檔案
path: path.resolve(__dirname, 'dist/js'), // 出口檔案位置,一定要是絕對路徑
filename: 'bundle.js' // 出口檔名
}
}
上面:將會打包。。。main.js檔案到。。。bundle.js檔案
多檔案輸入:
const path = require('path');
module.exports = {
entry: {
main: './src/js/main.js', // 入口檔案
a: './src/js/a.js'
},
output: { // 出口檔案
path: path.resolve(__dirname, 'dist/js'), // 出口檔案位置
filename: '[name].js' // 出口檔名,name就是entry的鍵名
}
}
四、自動生成HTML頁面檔案
(1)安裝html-webpack-plugin外掛
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install html-webpack-plugin --save-dev
(2)在webpack配置package.config.js中
const path = require('path');
var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/js/main.js', // 入口檔案
a: './src/js/a.js'
},
output: { // 出口檔案
path: path.resolve(__dirname, 'dist'), // 出口檔案位置
filename: 'js/[name].js' // 出口檔名
},
plugins: [
new htmlWebpackPlugin({
filename: '[name]-[hash].html', // 生成的HTML名,路徑為上面output中的path
template: './index.html', // 會與根目錄下的index.html相關聯,把根目錄下index的東西都放到生成的HTML中
inject: 'head' // 打包後的script放到head中
})
]
}
(3)傳參使用
1、引數
plugins: [
new htmlWebpackPlugin({
filename: 'index.html',
template: './index.html',
title: 'hello world'
})
]
在根目錄下的index.html中<h2><%= htmlWebpackPlugin.options.title %></h2>
生成的dist/index.html中
<h2>hello world</h2>
2、上線地址
output: { // 出口檔案
path: path.resolve(__dirname, 'dist'), // 出口檔案位置
filename: 'js/[name].js', // 出口檔名,
publicPath: 'http://cdn.com/' // 上線的地址
},
在生成的index.html中
<script type="text/javascript" src="http://cdn.com/js/main.js"></script>
<script type="text/javascript" src="http://cdn.com/js/a.js"></script>
3、html壓縮
title: 'hello world',
minify: {
removeComments: true, // 去掉註釋
collapseWhitespace: true // 去掉空格
}
4、多頁面應用,生成多個html檔案
new htmlWebpackPlugin({
filename: 'main.html',
template: './index.html',
title: 'hello world',
chunks: ['main', 'a'] // 會引入main.js和a.js
}),
new htmlWebpackPlugin({
filename: 'a.html',
template: './index.html',
title: 'hello world',
excludeChunks: ['main'] // 會引入除main以外的js
})
五、loader的配置
1、解析es6語法
(1)安裝babel
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install babel-loader babel-core babel-preset-env --save-dev
(2)配置webpack
module: {
rules: [
{
test: /\.js$/, // 匹配js檔案
loader: 'babel-loader',
exclude: path.resolve(__dirname, 'node_modules'), // 匹配時忽略這個目錄,提高打包速度
include: path.resolve(__dirname, 'src'), // 匹配時查詢的範圍
query: {
presets: ['env']
}
}
]
},
2、解析css
(1)安裝style-loader和css-loader
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install style-loader css-loader --save-dev
(2)配置webpack
{
test: /\.css$/,
loader: 'style-loader!css-loader' // 從右到左執行,所以注意順序
}
(3)在專案中經常有類似-webkit的字首,每次寫很麻煩,這裡就要用到postcss-loader,後處理loader
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install postcss-loader autoprefixer --save-dev // autoprefixer是自動補全
配置webpack
{
test: /\.css$/,
use: [
'style-loader', // 注意順序
{ loader: 'css-loader', options: { importLoaders: 1 } }, // 在css中使用@import引入其他檔案時,
'postcss-loader' // 不加importLoaders,postcss-loader不會操作引入的檔案
]
}
新建一個postcss.config.js檔案和webpack.config.js同級
module.exports = {
plugins: [
require('autoprefixer')
]
}
此時,如果你打包,並不會報錯,但是字首可能也沒有,所以需要在package.json中加入
"browserslist": [
"> 1%", // 全球瀏覽器使用率大於1%,最新兩個版本並且是IE8以上的瀏覽器,加字首
"last 2 versions",
"not ie <= 8"
]
3、解析less
(1)安裝
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install less less-loader --save-dev
(2)webpack的配置
{
test: /\.less$/,
loader: 'style-loader!css-loader!postcss-loader!less-loader' // 不用加importLoader,less-loader預設會有
}
4、解析sasssass的使用和less一樣,只要把less改為sass就行了
5、處理html模板檔案
(1)安裝html-loader
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install html-loader --save-dev
(2)配置
{
test: /\.html$/,
loader: 'html-loader'
}
(3)使用
layer.js
import tpl from './layer.html';
import './layer.less';
function layer () {
return {
name: 'layer',
tpl: tpl
}
}
export default layer;
app.js
import Layer from './components/layer/layer.js';
import './css/common.css';
const App = function () {
var app = document.getElementById('app');
var layer = new Layer();
app.innerHTML = layer.tpl;
}
App();
6、使用ejs模板檔案,字尾為tpl或ejs
(1)安裝
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install ejs-loader --save-dev
(2)配置
{
test: /\.tpl$/,
loader: 'ejs-loader'
}
(3)使用
layer.tpl
<div class="layer">
<div>this is <%= name %></div>
<% for (var i=0; i<arr.length; i++) { %>
<%= arr[i] %>
<% } %>
</div>
layer.js
import './layer.less';
import tpl from './layer.tpl'; // 返回是一個函式
function layer () {
return {
name: 'layer',
tpl: tpl
}
}
export default layer;
app.js
import Layer from './components/layer/layer.js';
import './css/common.css';
const App = function () {
var app = document.getElementById('app');
var layer = new Layer();
app.innerHTML = layer.tpl({
name: 'xueer',
arr: ['apple', 'oppo', 'xiaomi']
});
}
App();
7、用file-loader處理圖片
(1)安裝
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install file-loader --save-dev
(2)配置
{
test: /\.(png|jpg|gif|svg)$/i,
loader: 'file-loader'
}
(3)使用
layer.less
.layer {
width: 600px;
height: 200px;
background: url('../../assets/1.png');
div {
width: 400px;
height: 100px;
background: red;
}
.flex {
display: flex;
}
}
若是在.tpl或.ejs中使用
<img src="${ require('../../assets/1.png') }">
(4)也可以加引數
{
test: /\.(png|jpg|gif|svg)$/i,
loader: 'file-loader',
query: {
name: 'assets/[name]-[hash:5].[ext]'
}
}
8、使用url-loader處理圖片(會影響檔案大小)
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install url-loader --save-dev
{
test: /\.(png|jpg|gif|svg)$/i,
loader: 'url-loader',
query: {
limit: 30000, // 當圖片小於30kb的時候,圖片變為base64位,不打包
name: 'assets/[name]-[hash:5].[ext]'
}
}
9、通過image-webpack-loader和url-loader結合:先有image-webpack-loader打包,在通過url-loader
[email protected] MINGW64 /e/workspace/xampp/htdocs/text/demo/webpack-demo
$ cnpm install image-webpack-loader --save-dev
{
test: /\.(png|jpg|gif|svg)$/i,
loaders: [
'url-loader?limit=1000&name=assets/[name]-[hash:5].[ext]',
'image-webpack-loader'
]
}