wepback風頭正火 ,但是公司一直在用gulp,正好趕上年底活動,借此機會第一次嘗試了webpack,說實話webpack真的很強大,內容一層一層遞進。
這幾天跟着官網跑了一遍,然后寫了自己的配置文件,因為活動內容不多,很多強大的功能沒有用上,但是相信對於入門來說足夠了。
下面來總結並附上源碼
當 webpack 處理應用程序時,它會遞歸地構建一個依賴關系圖,其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle。
webpack支持的模塊語法有哪些?
ES6,CommonJs,Amd
webpack和gulp的區別?
Webpack可以通過眾多loader和plugin完成許多gulp上的功能,但Webpack本質在於模塊打包,而gulp的本質在於執行任務;使用webpack-stream包可以實現gulp和webpack的搭配使用
核心概念
1.入口:指定使用哪個模塊來作為構建內部依賴圖的開始,隨后打包成bundle
2.輸出:定義輸出生產的bundle的位置及文件名;
3.loader:讓webpack可以處理非js模塊;loader 可以將所有類型的文件轉換為webpack 能夠處理的有效模塊。
4. 插件:執行的任務范圍包括從打包優化和壓縮,一直到重新定義環境中的變量,目的在於完成一些loader無法完成的任務。
常用配置項
1.mode: ‘development’|| ‘production’ || ‘none’
2.entry: array || obj
3.output: {
path: path.resolve(__dirname, "dist"), // 輸出文件的目標路徑
filename:’bundle.js’,// 打包后的文件名
publicPath: ‘static’// 輸出解析文件目錄,url相對於html
}
4.module: {
rules: [
{
test: /\.js$/, // 指定使用此loader的文件
use: ‘babel-loader’,
options: { },
include: /src/, // 匹配項
exclude: /node_modules/ // 非匹配項
}
]
}
5.plugins: […instance]
6.devServer: {
host: ‘localhost’,
port: ‘8080’,
contentBase: Boolean|| string || array, // 服務器從哪里獲取內容
hot:boolean, // 是否開啟webpack模塊熱替換
open: Boolean, // 是否自動打開瀏覽器
proxy: { path: targetUrl}, // 代理
…others
}
7.resolve: {
alias: {
test: url
},
extensions: [.js, .json]
}
8.devtool: string || false
可選值:
cheap-eval-source-map
eval-source-map
cheap-source-map
source-map
cheap-module-eval-source-map
…others
常用loader及plugin
loader
Css-loader:解析css中資源路徑;
Sass-loader:sass轉碼為css
Postcss-loader:使webpack可以用postcss處理css
Px2rem-loader: px轉換為rem
Style-loader:將css以style標簽的形式插入到dom中
Babel-loader:轉碼js以提高兼容性
url-loader:圖片轉base64
webpack imagemin-webpack-plugin 壓縮圖片
file-loader:將文件輸出到輸出目錄並返回文件路徑
html-loader:處理html中資源路徑
eslint-loader:使js支持eslint
plugin
html-webpack-plugin:根據模板導出html文件,並注入bundle
DinePlugin: 創建編譯時可以進行配置的全局變量。
HashedModuleIdsPlugin: 根據模塊的相對路徑生成一個四位數的hash作為模塊id
extract-text-webpack-plugin:分離css
mini-css-extract-plugin:分離css
uglifyjs-webpack-plugin:壓縮js
optimize-css-assets-webpack-plugin:壓縮css
clean-webpack-plugin: 清空某個目錄
cli常用命令
--config 使用指定的配置文件
--env.key=value 指定環境變量
--mode=production 指定模式
--progress 打印編譯進度的百分比
--display-error-details 展示錯誤細節
--define 定義環境變量
-w 觀察文件變化,變化后重新執行構建流程
--hot 開啟模塊熱替換
--json > stats.json 將編譯結果的各種信息輸出為json文件
--profile
捕獲編譯時每個步驟的時間信息
配置文件編寫
前端常見需求:
1) Js壓縮
2) Css壓縮
3) Css提取
4) 小圖片轉base64
5) Px轉rem
6) Css前綴添加
7) Sass轉碼
8) Babel轉碼
9) 文件名加hash
10) 文件編碼格式轉換(常見utf-8與gbk互轉)
11) 代碼分離
12) Eslint
13) 模塊熱替換
14) 配置編譯過程的全局變量
15) 打包后的代碼注入html中
1. 常用模塊變量
__dirname:當前文件夾路徑
2. 常用占位符
[hash]:模塊標識符的hash(后拼接:‘:n’可指定長度)
[chunkhash]: chunk內容的hash(后拼接:‘:n’可指定長度)
[name]:模塊名稱
[id]: 模塊標識符
3. 配置文件使用commonjs編寫的,配置類型有下面幾種:
1) 導出一個配置對象
2) 導出一個函數
3) 導出一個promise
代碼分離
該功能可以把代碼分離到不同的 bundle 中,然后可以按需加載或並行加載這些文件。代碼分離可以用於獲取更小的 bundle,以及控制資源加載優先級,如果使用合理,會極大影響加載時間。
代碼分離的方式:
1.手動配置多個入口文件
2.使用webpack自帶的splitChunks功能
3.使用import()動態導入
下面附上自己的web.config.js
//生成html文件 npm i -D html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
//每次打包前清理目錄文件 npm i -D clean-webpack-plugin
const CleanWebpackPlugin = require('clean-webpack-plugin');
//js壓縮 npm i -D uglifyjs-webpack-plugin
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
//單獨打包css,webpack3是利用extract-text-webpack-plugin插件提取單獨打包css文件
//webpack4得使用mini-css-extract-plugin npm i -D mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
//壓縮css npm i -D optimize-css-assets-webpack-plugin
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
//用於打包后的文件轉碼 npm i webpack-encoding-plugin
const EncodingPlugin = require("webpack-encoding-plugin");
//提取公共模塊 請參考https://segmentfault.com/a/1190000012828879
//引入glob正則匹配多頁面 npm i -D glob
var glob = require('glob');
//安裝webpack npm i -D webpack@<version>(版本號)
//webpack4后將webpack-cli分別出來要自己安裝 npm in -D webpack-cli
const webpack = require('webpack');
//處理文件路徑的工具
const path = require('path');
//設置變量判斷是開發環境還是生產環境 npm i -D cross-env
const devMode = process.env.NODE_ENV !== 'production';
//獲取所有路口js,生成一個路徑對象.
var getEntry = function () {
var entry = {};
//首先我們先讀取我們的開發目錄
glob.sync('./source/**/*.js').forEach(function (name) {
var n = name.slice(name.lastIndexOf('source/') + 7, name.length - 3);
n = n.slice(0, n.lastIndexOf('/'));
//接着對路徑字符串進行了一些裁剪成想要的路徑
entry[n] = name;
});
console.log(entry);
/**
* entry = {
* 'crowd/index' : './source/main/index/index.js',
* 'index/index' : './source/content/index/index.js'
* }
*
**/
//最后返回entry 給 webpack的entry
return entry;
};
module.exports = {
entry: getEntry(), //入口文件
output: { //文件輸出位置
path: path.resolve(__dirname, 'dist'), //配置輸出路徑
filename: "js/[name].bundle.js", //文件輸出形式
chunkFilename: "js/[name].chunk.js",
publicPath: '/'//虛擬目錄,自動指向path編譯目錄
},
//tips:chunkFilename網上覺得靠譜的解釋
//chunkname是未被列在entry中,卻又需要被打包出來的文件命名配置。什么場景需要呢?在按需加載(異步)模塊的時候,
//這樣的文件是沒有被列在entry中的,如使用CommonJS的方式異步加載模塊:
// require.ensure(["modules/tips.jsx"], function(require) {
// var a = require("modules/tips.jsx");
// // ...
// }, 'tips');
//tips:一般來說,引入第三方庫有一下三種情況:
// 通過CDN引入;
// 通過npm 安裝並引入;
// 第三方js文件就在本地
resolve: {//一些配置項,如第三方的js文件就在本地,怎么通過webpack引入
alias: {
$: path.resolve(__dirname, './dist/jquery.js'),
jQuery: path.resolve(__dirname, './dist/jquery.js'),
}
},
plugins: [ //插件
require("autoprefixer"),//引入自動補全前綴,直接引入autoprefixer-loader並沒有生效,
//安裝postcss-loader並引入autoprefixer時生效,並創建postcss.config.js文件
new webpack.HotModuleReplacementPlugin(),//啟動模塊熱替換
new webpack.NamedModulesPlugin(), //用於啟動HMR時可以顯示模塊的相對路徑
new UglifyJsPlugin({}),//js壓縮
new MiniCssExtractPlugin({//css分離
filename: devMode ? 'css/[name].css' : 'css/[name].[hash:5].css',
chunkFilename: devMode ? 'css/[id].css' : 'css/[id].[hash:5].css',
}),
new OptimizeCSSAssetsPlugin({}),//css壓縮
//多頁應用時配置多個html時,那么就需要實例化該插件多次
new HtmlWebpackPlugin({
template: 'src/html/index.html',
excludeChunks: ['list', 'detail']//配置不允許注入的chunk
}),
new HtmlWebpackPlugin({
filename: 'list.html',
template: 'src/html/list.html',
chunks: ['common', 'list']//允許插入到模板中的一些chunk,不配置此項默認會將entry中所有的chunk注入到模板中
}),
new HtmlWebpackPlugin({
filename: 'detail.html',
template: 'src/html/detail.html',
chunks: ['common', 'detail']
}),
//用來項目的轉碼
new EncodingPlugin({
encoding: 'GB2312'
}),
//清除dist文件夾
new CleanWebpackPlugin(['dist'])
],
//模塊
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',//cnpm i -D babel-loader @babel/core @babel/preset-env webpack
options: {//npm i -S babel-polyfill 實現瀏覽器對不支持API的兼容(兼容舊環境、填補)
presets: ['@babel/preset-env']
}
}
],
exclude: /node_modules/
},
{
test: /\.(sa|sc|c)ss$/,
use: [//npm i -D style-loader css-loader
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,//因為MiniCssExtractPlugin不支持熱替換,所以當是生產環境時不啟用這個插件
'css-loader',
'postcss-loader',//npm i -D postcss-loader
// {網上還有這種寫法
// loader: 'postcss-loader',
// options: {
// plugins: () => [
// require('autoprefixer')
// ],
// }
// },
'sass-loader',//使用sass-loader要使用node-loader,npm i -D sass-loader node-sass
{
loader: 'px2rem-loader',//配合flexible實現移動端下的適配 npm i px2rem-loader
// options here
options: {
remUni: 75,
remPrecision: 8
}
}
]
},
{
test: /\.(jpg|png|gif|jpeg)$/,
use: [ {//npm i -D url-loader
loader: 'url-loader',// 在文件大小(單位 byte)低於指定的限制時,可以返回一個 DataURL。
options: {
limit: 10000,//設置字節限制
name: 'img/[name]_[hash:5].[ext]'
}
} ]
}
]
},
//配置開發服務功能 npm i -D webpack-dev-server
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
historyApiFallback: true,
hot: true,
port: 9000,
publicPath:'/',
}
};