webpack學習筆記

簡介

webpack能夠作的事
  • 代碼轉換
  • 文件優化
  • 代碼分割
  • 模塊合併
  • 自動刷新
  • 代碼校驗
  • 自動發佈
面試常見考點
  • webpack常見配置
  • webpack高級配置
  • ast抽象語法樹
  • webpack中的Tapable
  • 掌握webpack流程,手寫webpack
  • 手寫webpack中常見的loader
  • 手寫webpack中常見的plugin

webpack基礎配置

起步
  • 建立src--->index.js
  • npx webpack
  • 基礎配置
//webpack是node寫出來的,因此須要node的寫法

let path = require('path')   //核心模塊

module.exports = {
    mode: 'development',                    //默認兩種:production development
    entry: './src/index.js',                //入口
    output: {                               //出口
        filename: 'bundle.js', //打包後的文件名
        path: path.resolve(__dirname, 'dist'), //resolve把相對路徑解析成絕對路徑,__dirname意思是在當前目錄創建一個,路徑必須是一個絕對路徑
    }
}

script腳本

  • 手動配置:npx webpack --config webpack.config.js
  • 腳本配置:
"scripts": {
    "build": "webpack"
  }

//npm run build
  • 傳參npx webpack -- --config webpack.config.js

Html插件

npx webpack-dev-server

  • 開發服務,內部經過express實現這種服務
  • 並不真實打包文件,只是在內存中生成
htmlWebpackPlugin
  • 將打包後的js文件插入html文件,並放到build目錄下
let htmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    devServer: {                                //開發服務器的配置
        port: 3000,                             //設置端口號
        progress: true,                         //進度條
        contentBase: '/.build',                  //指定靜態目錄
        compress: true
    },
    output: {
        filename: 'bundle.[hash:8].js',         //文件名
        path: path.resolve(__dirname, 'dist'),
    },
    plugins: [                                  //數組 放着全部的webpack插件
        new htmlWebpackPlugin({
            template: './src/index.html',       //模板
            filename: 'index.html',             //打包後的文件名
            minify: {                           //打包後的html也壓縮
                removeAttributeQuotes: true,    //刪除屬性的雙引號
                collapseWhitespace: true,       //摺疊空行
            },
            hash: true                          //html文件加上哈希戳
        })
    ]
}

css配置

loader: Webpack自己只能處理 JavaScript 模塊,若是要處理其餘類型的文件,就須要使用 loader 進行轉換。

Loader 能夠理解爲是模塊和資源的轉換器,它自己是一個函數,接受源文件做爲參數,返回轉換的結果css

css配置

  • css-loader 解析@import這種語法
  • style-loadercss插入到head的標籤中
  • loader的特色:但願單一
  • loader的用法:字符串只用一個loader,多個loader須要[]
  • loader的順序:默認是從右向左執行       從下往上

優先級

{
    loader: 'style-loader',
    options: {
        insertAt: 'top'    //確保優先級
    }
}

處理lesssassstylus

  • yarn add less less-loader
  • yarn add node-sass sass-loader
  • yarn add stylus stylus-loader
module.exports = {
    module: {                                       //模塊
        rules: [                                    //規則 
                                        //loader的特色:但願單一
            //{ test: /\.css$/, use: ['style-loader', 'css-loader'] }   //第一種:寫法
                                        //loader還能夠寫成對象方式
            {
                                        //處理less文件
                test: /\.css$/,
                use: [{
                        loader: 'style-loader',
                        options: {
                            insertAt: 'top'    //確保優先級
                        }
                    },
                    'css-loader',              //@import  解析路徑
                    'less-loader'              //把less ---->css  
                ]
            }
        ]
    }
}

抽離CSS的插件

  • 默認打包後只能插入<style>標籤內,咱們但願抽離成<link>形式
  • 經過 mini-css-extract-plugin這個插件
  • yarn add mini-css-extract-plugin -D
  • 插件都是類插件的使用順序沒有前後
let MiniCssExtractPlugin = require('mini-css-extract-plugin')

//配置plugin
plugins: [
        new MiniCssExtractPlugin({
            filename: 'main.css',
        })
    ],

//配置module    
module: {
        rules: [{
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
            }
        ]
    }

自動添加前綴

  • autoprefixer
  • 前提要用postcss-loader
  • yarn add postcss-loader autoprefixer
//配置module
//先處理post-css再處理css
module: {
        rules: [{
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader','postcss-loader']       //加上post-css
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader']
            }
        ]
    }
//建立postcss.config.js文件並配置

module.exports = {
    plugins: [require('autoprefixer')]
}
壓縮 css(同時保證 js的壓縮)
  • 經過optimize-css-assets-webpack-plugin
  • yarn add optmize - css - assets - webpack - plugin - D
  • uglifyjs-webpack-plugin
let path = require('path')
let htmlWebpackPlugin = require('html-webpack-plugin')
let MiniCssExtractPlugin = require('mini-css-extract-plugin')
let OptimizeCss = require('optimize-css-assets-webpack-plugin')
let UglifyJsPlugin = require('uglifyjs-webpakc-plugin')

module.exports = {
    Optimization: { //***優化項,用了這個插件以後就必須用一下Uglifyjs壓縮js
        minimizer: [
            new UglifyJsPlugin({
                cache: true, //是否用緩存
                parallel: true, //是否並行打包
                sourceMap: true
            }),
            new OptimizeCss()
        ]
    },
    devServer: {
        port: 3000,
        progress: true,
        contentBase: '/.build'
    },
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'bundle.[hash:8].js',
        path: path.resolve(__dirname, 'dist'),
    },
    plugins: [
        new htmlWebpackPlugin({
            template: './src/index.html',
            filename: 'index.html',
            minify: {
                removeAttributeQuotes: true,
                collapseWhitespace: true,
            },
            hash: true
        }),
        new MiniCssExtractPlugin({
            filename: 'main.css'
        })
    ],
    module: {
        rules: [
            //{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader, //***建立link標籤,引用
                    'css-loader',
                    'less-loader',
                    'postcss-loader'

                ]
            }
        ]
    }
}

JS配置

轉化es6語法

babel
  • yarn add babel-loader @babel/core @babel/preset-env -D
  • 配置module
module: {
        rules: [{
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {          //用babel-loader es6---->es5
                        presets: [
                            '@babel/preset-env'
                        ]
                    }
                }
            }
        ]
    }

配置提案裏支持的語法

class A{
    a = 1;
}
  • yarn add @babel/plugin-proposal-class-properties -D
{
    test: /\.js$/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: [
                '@babel/preset-env'
            ],
            plugins: [
                '@babel/plugin-proposal-class-properties'
            ]
        }
    }
}

支持裝飾器語法

function log(target) {
    console.log(target, '23')
}

log(A)
  • yarn add @babel/plugin-proposal-decorators -D
配置 module
module: {
        rules: [{
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: { //用babel-loader es6---->es5
                        presets: [
                            '@babel/preset-env'
                        ],
                        plugins: [
                            ['@babel/plugin-proposal-class-properties'],
                            ['@babel/plugin-proposal-decorators',{"legacy":true}],
                            ['@babel/plugin-transform-runtime']
                        ]
                    }
                }
            }
        ]
    }

處理JS語法及校驗

function *gen(params){
        yield 1;     
    }
    console.log(gen().next());  //內置API
    
// Uncaught ReferenceError: regeneratorRuntime is not defined
babel-runtime
  • yarn add @babel/plugin-transform-runtime -D
  • yarn add @babel/runtime
module: {
        rules: [{
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: { //用babel-loader es6---->es5
                        presets: [
                            '@babel/preset-env'
                        ],
                        plugins: [
                            ['@babel/plugin-proposal-class-properties'], ['@babel/plugin-proposal-decorators',{"legacy":true}],
                            ['@babel/plugin-transform-runtime']
                        ]
                    }
                },
                include:path.resolve(__dirname,'src'),  //包括查找範圍
                exclude:/node_module/                   //排除查找範圍
            }
        ]
    }
@babel/polyfill
'aaa'.include('a')  //ES7語法

//實例上的方法默認都不會解析
  • yarn add @babel/polyfill
//a.js
require('@babel/polyfill')
'aaa'.include('a')
eslint
  • yarn add eslint eslint-loader
module: {
        rules: [     //loader默認從右向左執行 從下到上,寫的太多容易亂,寫到一塊兒刪除不方便
            {
                test:\.js$/,
                use:{
                    loader:'eslint-loader',
                    options:{
                        enforce:'pre'   //previous -> normal-> post 順序執行
                    }
                }
            }
            /*...*/
        ]
}
  • 選擇好配置,下載.eslintrc.jsonconfiguration

全局變量引入問題

  • 第三方模塊引用
  • yarn add jquery
import $ form 'jqurey'
console.log($) 
console.log(window.$) //undefined,並不會掛載到window上

如何將變量暴露給window?html

expose-loader (內聯 loader)
  • yarn add expose-loader
import $ from 'expose-loader?$!jquery'   //將jquery做爲$暴露給全局
  • 也能夠在webpack.config.js中配
module: {
        rules: [{
                test: require.resolve('jquery'),
                use: 'expose-loader?$!jquery'
                }
        ]
    }
  • 在每一個模塊中注入$對象
//webpack.config.js
let Webpack = require('webpack')
 new Webpack.ProvidePlugin({
            //再每一個模塊中都注入$符
    jqurey: '$'
})
//index.js
console.log($)   //只是在每一個模塊中都注入一個`$`
//此時window.$   //undefined
cdn外部路徑引入
<script src="https://cdn.bootcss.com/jquery/3.3.1/core.js"></script>
//若是此時js也引入jquery會致使重複
import $ form jquery
externals: {
        jquery: 'jQuery'   //告訴webpack從外部引入,並不須要打包,忽略
    },
總結
  • expose-loader:暴露到window上
  • providePlugin:給每一個提供一個
  • 引入不打包
loader類型
  • pre             前面執行的loader
  • normal        普通的loader
  • liader        內聯loader
  • post            後置loader

圖片處理

圖片引入方式
  • js中建立圖片來引入
let image = new Image()
image.src = './logo.png'
document.body.appendChild(image) //打包完,其實就是一個普通的字符串,並無真正的引入圖片

file-loader

  • yarn add file-loader
  • 默認在內部生成圖片,到build目錄下,而且把生成的路徑的名字返回回來
//webpack.config.js

module: {
        rules: [{
                test: /\.(png|jpg|gif)$/,
                use: 'file-loader'
            }
        ]
}
//index.js

import logo from './logo.png' //把圖片引入,生成一個哈希戳的logo,返回的結果是一個新的圖片

console.log(logo)

let image = new Image();
image.src = logo;
document.body.appendChild(image)
  • css中引入background('url')
  • <img src="" alt="">

打包文件分類

打包多頁應用

配置source-map

相關文章
相關標籤/搜索