webpack4.0剛剛發佈,官網自稱4.0最大的特色就是零配置。本文就詳細介紹一下webpack4.0實戰那些事兒。javascript
打包機css
WebPack能夠看作是模塊打包機:它作的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),並將其打包爲合適的格式以供瀏覽器使用。html
構建前端
構建就是把源代碼轉換成發佈到線上的可執行 JavaScrip、CSS、HTML 代碼,包括以下內容。java
構建實際上是工程化、自動化思想在前端開發中的體現,把一系列流程用代碼去實現,讓代碼自動化地執行這一系列複雜的流程。 構建給前端開發注入了更大的活力,解放了咱們的生產力。node
npm init -y
複製代碼
在要進行打包的目錄下初始化npm, 在控制檯執行以上命令後會生成一個package.json
的文件。react
npm install webpack webpack-cli -D
複製代碼
由於從4.0開始,webpack拆分開兩個包分別是webpack
和webpack-cli
jquery
webpack.config.js
module.exports = {
entry:配置入口文件的地址
output:配置出口文件的地址
module:配置模塊,主要用來配置不一樣文件的加載器
plugins:配置插件
devServer:配置開發服務器
}
複製代碼
接下來咱們就一一介紹一下它們的配置。webpack
npm install webpack-dev-server -D
複製代碼
devServer:{
contentBase:path.resolve(__dirname,'dist'),// 配置開發服務運行時的文件根目錄
host:'localhost',// 開發服務器監聽的主機地址
compress:true, // 開發服務器是否啓動gzip等壓縮
port:8080 // 開發服務器監聽的端口
}
複製代碼
"scripts": {
"dev": "webpack-dev-server --open --mode development "
}
複製代碼
notegit
從4.0開始,運行webpack時必定要加參數 --mode development
或者--mode production
,分別對應開發環境和生產環境。
module
loader
module
主要用來配置不一樣文件的加載器。談到加載就離不開loader
,那什麼是loader
呢?
loader的概念
經過使用不一樣的Loader,Webpack能夠要把不一樣的文件都轉成JS文件,好比CSS、ES6/七、JSX等。
test
:匹配處理文件的擴展名的正則表達式use
:loader名稱,就是你要使用模塊的名稱include/exclude
:手動指定必須處理的文件夾或屏蔽不須要處理的文件夾query
:爲loaders提供額外的設置選項
loader
的三種寫法
install
npm install style-loader css-loader -D
複製代碼
配置加載器
module: {
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader'],
include:path.join(__dirname,'./src'),
exclude:/node_modules/
}
]
}
複製代碼
note
**注意:**加載器的加載順序爲從右至左。即先用css-loader
解析而後用style-loader
將解析後的css
文件添加到Head
標籤中。
install
npm install file-loader url-loader html-withimg-loader -D
複製代碼
file-loader
解決CSS等文件中的引入圖片路徑問題url-loader
當圖片較小的時候會把圖片BASE64編碼,大於limit參數的時候仍是使用file-loader 進行拷貝配置加載器
{
test: /\.(png|jpg|gif|svg|bmp|eot|woff|woff2|ttf)$/,
loader: {
loader: 'url-loader',
options: {
limit: 5 * 1024,// 圖片大小 > limit 使用file-loader, 反之使用url-loader
outputPath: 'images/'// 指定打包後的圖片位置
}
}
}
複製代碼
usage - 手動添加圖片
let logo = require('./images/logo.png');
let img = new Image();
img.src = logo;
document.body.appendChild(img);
複製代碼
usage - 在CSS中引入圖片
.img-bg{
background: url(./images/logo.png);
width:173px;
height:66px;
}
複製代碼
usage - 在HTML中使用圖片
{
test:/\.(html|html)$/,
use:'html-withimg-loader',
include:path.join(__dirname,'./src'),
exclude:/node_modules/
}
複製代碼
npm install less less-loader node-sass sass-loader -D
複製代碼
把編譯好的代碼放到head裏面
{
test: /\.css$/,
loader: ['style-loader', 'css-loader']
}, {
test: /\.less$/,
loader: ['style-loader', 'css-loader']
}, {
test: /\.scss$/,
loader: ['style-loader', 'css-loader']
}
複製代碼
把編譯好的代碼放到單獨的文件裏面
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
let cssExtract = new ExtractTextWebpackPlugin('css.css');
let lessExtract = new ExtractTextWebpackPlugin('less.css');
let sassExtract = new ExtractTextWebpackPlugin('sass.css');
...
{
test: /\.css$/,
loader: cssExtract.extract({
use: ['css-loader?minimize']
})
}, {
test: /\.less$/,
loader: lessExtract.extract({
use: ['css-loader?minimize', 'less-loader']
})
}, {
test: /\.scss$/,
loader: sassExtract.extract({
use: ['css-loader?minimize', 'sass-loader']
})
}
複製代碼
爲了瀏覽器的兼容性,有時候咱們必須加入-webkit,-ms,-o,-moz這些前綴
install
npm install postcss-loader autoprefixer -D
複製代碼
usage
postcss-loader
須要配置 postcss.config.js
文件,postcss.config.js 內容以下:
module.exports = {
plugins: [
require('autoprefixer')
]
}
複製代碼
// 把 post-laoder push 到css的loader數組中
{
test: /\.css$/,
loader: ['style-loader', 'css-loader', 'postcss-loader']
}, {
test: /\.less$/,
loader: ['style-loader', 'css-loader', 'less-loader']
}, {
test: /\.scss$/,
loader: ['style-loader', 'css-loader', 'sass-loader']
}
複製代碼
Babel實際上是一個編譯JavaScript的平臺,能夠把ES6/ES7,React的JSX轉義爲ES5。
install
npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 babel-preset-react -D
複製代碼
配置加載器
{
test:/\.jsx?$/,
use: {
loader: 'babel-loader',
options: {
presets: ["env","stage-0","react"]// env --> es6, stage-0 --> es7, react --> react
}
},
include:path.join(__dirname,'./src'),
exclude:/node_modules/
}
複製代碼
plugins
配置插件
咱們但願自動能產出HTML文件,並在裏面引入產出後的資源。
install
npm install html-webpack-plugin -D
複製代碼
usage
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 指定產出的模板
filename: 'base.html', // 產出的文件名
chunks: ['common', 'base'], // 在產出的HTML文件裏引入哪些代碼塊
hash: true, // 名稱是否哈希值
title: 'base', // 能夠給模板設置變量名,在html模板中調用 htmlWebpackPlugin.options.title 能夠使用
minify: { // 對html文件進行壓縮
removeAttributeQuotes: true // 移除雙引號
}
})
]
複製代碼
由於CSS的下載和JS能夠並行,當一個HTML文件很大的時候,咱們能夠把CSS單獨提取出來加載
install
npm install extract-text-webpack-plugin@next -D
複製代碼
usage
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
let cssExtract = new ExtractTextWebpackPlugin('css.css');
let lessExtract = new ExtractTextWebpackPlugin('less.css');
let sassExtract = new ExtractTextWebpackPlugin('sass.css');
...
module: {
rules: [
{
test: /\.css$/,
loader: cssExtract.extract({
use: ['css-loader?minimize']
})
}, {
test: /\.less$/,
loader: lessExtract.extract({
use: ['css-loader?minimize', 'less-loader']
})
}, {
test: /\.scss$/,
loader: sassExtract.extract({
use: ['css-loader?minimize', 'sass-loader']
})
}
]
}
...
plugins: [
cssExtract,
lessExtract,
sassExtract
]
複製代碼
處理圖片路徑問題
const PUBLIC_PATH='/';
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath:PUBLIC_PATH
}
複製代碼
有時項目中沒有引用的文件也須要打包到目標目錄
install
npm install copy-webpack-plugin -D
複製代碼
usage
const CopyWebpackPlugin = require('copy-webpack-plugin');
plugins: [
new CopyWebpackPlugin([{
from: path.join(__dirname, 'public'), // 從哪裏複製
to: path.join(__dirname, 'dist', 'public') // 複製到哪裏
}])
]
複製代碼
install
npm install clean-webpack-plugin -D
複製代碼
usage
const CleanWebpackPlugin = require('clean-webpack-plugin');
plugins: [
new CleanWebpackPlugin([path.join(__dirname, 'dist')])
]
複製代碼
install
npm install uglifyjs-webpack-plugin -D
複製代碼
usage
onst UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
plugins: [
new UglifyjsWebpackPlugin()
]
複製代碼
webapck經過配置能夠自動給咱們source maps文件,map文件是一種對應編譯文件和源文件的方法
usage
devtool:'eval-source-map'
複製代碼
devtool的參數詳解
source-map
把映射文件生成到單獨的文件,最完整最慢cheap-module-source-map
在一個單獨的文件中產生一個不帶列映射的Mapeval-source-map
使用eval打包源文件模塊,在同一個文件中生成完整sourcemapcheap-module-eval-source-map
sourcemap和打包後的JS同行顯示,沒有映射列import _ from 'lodash';
alert(_.join(['a','b','c'],'@'));
複製代碼
new webpack.ProvidePlugin({
_:'lodash'
})
複製代碼
當代碼發生修改後能夠自動從新編譯
watch: true,
watchOptions: {
ignored: /node_modules/, //忽略不用監聽變動的目錄
aggregateTimeout: 500, // 文件發生改變後多長時間後再從新編譯(Add a delay before rebuilding once the first file changed )
poll:1000 //每秒詢問的文件變動的次數
}
複製代碼
若是你有單獨的後端開發服務器 API,而且但願在同域名下發送 API 請求 ,那麼代理某些 URL 會頗有用。
//請求到 /api/users 如今會被代理到請求 http://localhost:9000/api/users。
proxy: {
"/api": "http://localhost:9000",
}
複製代碼
指定extension以後能夠不用在require或是import的時候加文件擴展名,會依次嘗試添加擴展名進行匹配
resolve: {
//自動補全後綴,注意第一個必須是空字符串,後綴必定以點開頭
extensions: ["",".js",".css",".json"],
},
複製代碼
配置別名能夠加快webpack查找模塊的速度
const bootstrap = path.join(__dirname,'node_modules/bootstrap/dist/css/bootstrap.css');
resolve: {
alias: {
'bootstrap': bootstrap
}
}
複製代碼
install
npm install expose-loader -D
複製代碼
action
把模塊的導出暴露給全局變量,
usage-1
require("expose-loader?libraryName!./file.js");
複製代碼
usage-2
rules: [{
test: require.resolve('jquery'),// 注意 這裏是require的resolve 方法
use: {
loader: "expose-loader",
options: "$"
}
}]
複製代碼
有時候咱們的頁面能夠不止一個HTML頁面,會有多個頁面,因此就須要多入口
usage
// 多個入口,能夠給每一個入口添加html模板
entry: {
index: './src/index.js',
main:'./src/main.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash].js',
publicPath:PUBLIC_PATH
},
plugins: [
new HtmlWebpackPlugin({
minify: {
removeAttributeQuotes:true
},
hash: true,
template: './src/index.html',
chunks:['index'],
filename:'index.html'
}),
new HtmlWebpackPlugin({
minify: {
removeAttributeQuotes:true
},
hash: true,
chunks:['login'],
template: './src/login.html',
filename:'login.html'
})]
]
複製代碼
若是咱們想引用一個庫,可是又不想讓webpack打包,而且又不影響咱們在程序中以CMD、AMD或者window/global全局等方式進行使用,那就能夠經過配置externals。
webpack.config.js
externals: {
jquery: "jQuery"
//若是要在瀏覽器中運行,那麼不用添加什麼前綴,默認設置就是global
},
複製代碼
index.js
const $ = require("jquery");
const $ = window.jQuery;
複製代碼