原文連接:banggan.github.io/2019/05/09/…css
終於忙完了論文,能夠愉快的開始學習了,重拾起重學前端、webpack以及Vue的源碼解讀做爲入職前的複習吧。整個webpack系列將分紅五個大的部分進行,以webpack4.0爲文檔進行解讀,從簡單的概念解讀到最後的實現。 整個知識點涉及範圍: html
使用loader來預處理文件,把不一樣的靜態資源(模塊的結尾不是js的模塊)打包成js文件前端
npm install file-loader -D
module.exports = {
//打包項目的入口文件
entry: './src/index.js',
module:{
rules:[{
test:/\.(jpg|png|gif)$/,//打包以jpg、png、gif結尾的全部圖片文件
use:{
loader:'file-loader',
options:{//placeholder 佔位符
name:'[name]_[hash].[ext]',//保持原圖片的名字+hash值和後綴,主要單引號
outputPath:'image/'//打包圖片的位置
}
}
}]
}
}
複製代碼
url-loader基本能實現file-loader的打包功能,適用於小圖片的打包vue
因此,當圖片的大小小於limit值時會把圖片打包成base64格式,大於limit值則按照file-loader打包成圖片文件node
npm install url-loader -D
module.exports = {
module:{
rules:[{//打包以jpg、png、gif結尾的全部圖片文件
test:/\.(jpg|png|gif)$/,
use:{
loader:'url-loader',
options:{//placeholder 佔位符
name:'[name]_[hash].[ext]',//保持原圖片的名字+hash值和後綴,主要單引號
outputPath:'image/',//打包圖片的位置
limit:2048
}
}]
}
}
複製代碼
須要使用css-loader、style-loaderwebpack
實現方式:git
npm install css-loader style-loader -D
module.exports = {
module: {
rules: [{//打包css文件
test:/\.css$/,
use:['style-loader','css-loader']
}]
}
}
複製代碼
須要使用sass-loader、node-sasses6
npm install sass-loader node-sass -D
module.exports = {
module: {
rules: [{
test: /\.scss$/,
use:['style-loader','css-loader','sass-loader']
}]
}
};
複製代碼
在配置中,有三個loader,執行順序是從下到上,從右到左。在打包scss文件時,首先執行sass-loader:對sass翻譯成css文件,在掛載到css-loader,最後style-loader.github
爲了兼容不一樣的瀏覽器,在寫樣式的時候須要加上適用不一樣瀏覽器的前綴,如-o、-webkit、-moz等web
-安裝loader實現:npm install postcss-loader autoprefixer -D
-在根目錄建立postcss.config.js
moudle.exports ={
plugins:[
require('autoprefixer')
]
}
複製代碼
module.exports = {
module: {
rules: [{
test:/\.scss$/,
use:[
'style-loader',
'css-loader',
'sass-loader',
'postcss-loader']
}]
}
}
複製代碼
modules:true
開啓css的模塊化打包,在引入的時候注意區分場景:scss文件經過import引入其餘scss文件,致使打包的時候引入的scss文件打包錯誤
實現:importLoader:2
在webpack.config.js中添加loader的配置
module:{
rules:[{//打包scss文件
test:/\.scss$/,
use:[
'style-loader',
{
loader:'css-loader',
options:{
importLoaders:2,//index.scss中經過import引入其餘的scss文件,引入的scss文件在打包的時候也將依次通過全部的loader
modules:true
}
},
'sass-loader',
'postcss-loader']
}]
}
複製代碼
在阿里巴巴矢量圖標庫中,把須要的字體圖標下載到本地,解壓。將iconfont.eot iconfont.svg iconfont.ttf iconfont.woff 四種圖片文件放入到項目中,在src中新建一個放字體圖標的文件夾font。將iconfont.css文件拷貝到項目中,修改對應字體的引用路徑。
npm i file-loader -D
module.exports = {
...
module: {
rules: [{
test: /\.(eot|ttf|svg|woff)$/,
use:{
loader:'file-loader'
}
},
]
}]
}
}
複製代碼
如遇到json、scv、xml文件須要打包時,使用csv-loader 和 xml-loader實現。
module.exports = {
module: {
rules: [{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
{
test: /\.xml$/,
use: [
'xml-loader'
]
}]
}
}
複製代碼
loaders能夠將各個類型的靜態資源打包成webpack能處理的模塊,而plugins有更強大的功能。它能夠從打包優化和壓縮,一直到從新定義環境中的變量。
plugin能夠在webpack運行到某一個時刻,自動完成一些事情。
npm install html-webpack-plugin -D
在src中建立一個html的模板,在HtmlWebpackPlugin的配置中引入該模板,打包後生成和模板相似的html文件並引入打包的js文件。
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js'
},
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html'
})]
}
複製代碼
先刪除上一次打包的dist文件,再執行打包
npm install clean-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(['dist']), // 在打包以前,能夠刪除dist文件夾下的全部內容
]
}
複製代碼
__webpack_public_path__ = myRuntimePublicPath
module.exports = {
mode: 'development',
entry: {
main: './src/index.js',
sub: './src/index.js'
},
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html'
}), new CleanWebpackPlugin(['dist'])],
output: {
publicPath: 'http://cdn.com.cn', //加入cdn地址
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
}
}
複製代碼
SourceMap是一個映射關係,打包文件和源文件的映射關係,用於開發者的調試。
在devtool中進行設置:devtool: 'source-map'
打包速度會下降,在dist裏面會有map映射文件
經常使用設置devtool說明:
development環境推薦使用: devtool: 'cheap-module-eval-source-map'
production環境推薦使用: devtool: 'cheap-module-source-map'
場景:每次在src裏編寫完代碼都須要手動從新運行 npm run bundle,如何自動解決?
-安裝:npm install webpack-dev-server –D
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: './dist',
open: true,
port: 8080
proxy:{//配置跨域,訪問的域名會被代理到本地的3000端口
'/api': 'http://localhost:3000'
}
}
}
複製代碼
{
"name": "banggan",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"bundle": "webpack",
"watch": "webpack --watch",
"start": "webpack-dev-server",
},
}
複製代碼
npm run server
運行本身寫的相似webpackdevserver的工具{
"name": "banggan",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"bundle": "webpack",
"watch": "webpack --watch",
"start": "webpack-dev-server",
"server" : "node server.js"
},
}
複製代碼
npm install express webpack-dev-middleware -D
webpack(config)
const express = require('express'); //引入express
const webpack = require('webpack');//引入webpack
const webpackDevMiddleware = require('webpack-dev-middleware');
const config = require('./webpack.config.js');//引入配置文件
const complier = webpack(config); //編譯一次嗎,打包一次代碼
const app = express();//建立express實例
app.use(webpackDevMiddleware(complier, {}));
app.listen(3000, () => {//監聽3000端口
console.log('server is running');
});
複製代碼
場景:在程序運行中。替換、添加、替換某個模塊,不須要從新加載整個頁面,實現交互時更新。
在 webpack.config.js 中,添加配置
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true,//開啓熱更新功能
hotOnly: true//若是html功能沒有實現,也不讓瀏覽器刷新
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(['dist']),
new webpack.HotModuleReplacementPlugin()//使用熱模塊插件
],
}
複製代碼
//若是模塊啓用了HMR,就能夠用 module.hot.accept(),監聽模塊的更新。
if (module.hot) {
module.hot.accept('./library.js', function() {
// 使用更新過的 library 模塊執行某些操做...
})
}
複製代碼
//拒絕給定依賴模塊的更新,使用 'decline' 方法強制更新失敗。
module.hot.decline(
dependencies // 能夠是一個字符串或字符串數組
)
複製代碼
注意:引入css文件時,用框架Vue,React 時,不須要寫 module.hot.accept(),由於在使用css-loader,vue-loader,babel-preset時,均配置好了HMR,不須要本身從新寫 若是文件沒有內置HMR,須要本身手動寫監聽模塊更新代碼
//preset-env語法轉換
npm install babel-loader @babel/core @babel/preset-env -D
//兼容低版本瀏覽器的語法,函數的補充
npm install --save @babel/polyfill
複製代碼
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, //排除在外:在node_modules中的js,babel-loader不生效
loader: "babel-loader" ,
options:{
"presets": [["@babel/preset-env",{
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1",
},//運行在大於**版本的瀏覽器上,,已經支持es6的高瀏覽器不須要轉換爲es5
useBuiltIns:'usage' //按需添加polyfill,把業務代碼中的新語法新函數都轉成低版本瀏覽器兼容的
}]]
}
}
]
}
複製代碼
import "@babel/polyfill";
注意若是不是打包業務代碼,而是寫的類庫、或者z組件庫的時候不能使用@babel/polyfill實現,由於會致使聲明的變量變成全局變量,污染全局環境。使用
plugin-transform-runtime
實現
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
npm install --save @babel/runtime-corejs2
複製代碼
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" ,
options:{
"plugins": [["@babel/plugin-transform-runtime",{
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false
}]]
}
}
]
}
複製代碼
因爲babel配置的內容較多,官網推薦在根目錄下建立屬於babel的配置文件.babelrc文件
因爲babel須要配置的內容很是多,咱們須要在項目根目錄下建立一個 .babelrc 文件。 就不須要在 webpack.config.js 中寫 babel 的配置了。 在 .babelrc 中:
{
"plugins": [["@babel/plugin-transform-runtime", {
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false
}]]
}
複製代碼
module.exports = {
mode: 'development', //開發環境進行打包,打包的代碼不會壓縮
devtool: 'cheap-module-eval-source-map',//不帶列信息,只對業務代碼進行sourcemap的生成
entry: {//配置入口文件
main: './src/index.js'
},
devServer: {//配置webpack,開發環境的調試
contentBase: './dist',//啓動服務器的目錄
open: true,//打開新的端口號8080
port: 8080,
hot: true,//打開熱替換功能
hotOnly: true
},
module: {//對不一樣的文件進行打包規則
rules: [{
test: /\.js$/, //對js文件的babel-loader打包,其配置在.babelrc文件中
exclude: /node_modules/, //排除在外:在node_modules中的js,babel-loader不生效
loader: 'babel-loader',
}, {
test: /\.(jpg|png|gif)$/,//對圖片進行打包
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 10240//小於10240以base64的形式進行打包
}
}
}, {
test: /\.(eot|ttf|svg)$/,//字體文件的打包
use: {
loader: 'file-loader'
}
}, {
test: /\.scss$/,//scss文件的打包,先用postcss-loader,在用sass-loader進行解析,最後css-loader進行掛載
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
}, {
test: /\.css$/,//css文件的打包,沒有sass-loader的解析
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(['dist']),//自動清空上一次打包
new webpack.HotModuleReplacementPlugin()//熱替換插件
],
output: {//出口文件
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
}
}
複製代碼