webpack4-用之初體驗,一起敲它十一遍,webpack4-初體驗

眾所周知,webpack進入第4個大版本已經有2個月的時間了,而且webpack團隊升級更新的速度也是非常的驚人

在寫下如下內容的時候webpack已經出到了4.6的版本了,劍指5.0應該是指日可待了,當然這些都是個人的臆想,并不代表任何意見

既然我們已經迎接了webpack4的到來了,那么就一起來使用一下,即使你沒用過之前的版本,沒關系,我們重新出發,將工作中常用到的配置寫給大家來看

非友情提示:由于webpack使用起來并不能僅看代碼就方便理解,所以有圖有真相的才是正解,于是乎本文配圖很多,真的是很多

首先,既來之,則安之

  • 需要先在項目中npm init初始化一下,生成package.json
  • 建議node版本安裝到8.2以上


// webpack4中除了正常安裝webpack之外,需要再單獨安一個webpack-cli

npm i webpack webpack-cli -D

npm i -D 是 npm install --save-dev 的簡寫,是指安裝模塊并保存到 package.json 的 devDependencies中,主要在開發環境中的依賴包

webpack4可以支持0配置打包,這里所說的0配置又是什么呢?當然在開發者眼中0配置的東西,那根本是無法用的,因為不夠智能,那么我們就來看看做到了哪些0配置

在使用webpack進行打包的時候,默認情況下會將src下的入口文件(index.js)進行打包


// node v8.2版本以后都會有一個npx
// npx會執行bin里的文件

npx webpack     // 不設置mode的情況下 打包出來的文件自動壓縮

npx webpack --mode development  // 設置mode為開發模式,打包后的文件不被壓縮

當執行npx webpack命令的時候,webpack會自動查找項目中src目錄下的index.js文件,然后進行打包,生成一個dist目錄并存在一個打包好的main.js文件

這些算是0配置的操作了,名字都是定義好的,不能變,想想也很雞肋

c1b8e61ec0db60489c28f03796f4aeda14b321b2

webpack的使用還是在我們的配置方面,下面就進入我們的常規操作環節

webpack是基于Node的

在項目下創建一個webpack.config.js(默認,可修改)文件來配置webpack


module.exports = {
    entry: '',               // 入口文件
    output: {},              // 出口文件
    module: {},              // 處理對應模塊
    plugins: [],             // 對應的插件
    devServer: {},           // 開發服務器配置
    mode: 'development'      // 模式配置
}


以上就是webpack的正常配置模塊

啟動devServer需要安裝一下webpack-dev-server


npm i webpack-dev-server -D

59252be6289b05f62e12bcfa82aea3bc794f5db3

按照項目的結構,我們就從0開始去寫一下配置吧


// webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/index.js',    // 入口文件
    output: {
        filename: 'bundle.js',      // 打包后的文件名稱
        path: path.resolve('dist')  // 打包后的目錄,必須是絕對路徑
    }
}

上面就可以說是實現了最簡單的webpack配置了,那接下來就打包一下看看

082a4d21bdc05e2b1dbb7d4a93216a15543d196f

配置執行文件

工作當中我們打包編譯的時候一般都執行npm run dev這樣的命令,既然是通過npm執行的命令,我們就應該找到package.json里的執行腳本去配置一下命令,這里如下圖所示

185164d74eec2549a3be8f8df1431b91ca94d86a

npm run build就是我們打包后的文件,這是生產環境下,上線需要的文件

npm run dev是我們開發環境下打包的文件,當然由于devServer幫我們把文件放到內存中了,所以并不會輸出打包后的dist文件夾

通過npm run build之后會生成一個dist目錄文件夾,就和上面打包后的樣子一樣了

多個入口可以有兩種實現方式進行打包

  • 一種是沒有關系的但是要打包到一起去的,可以寫一個數組,實現多個文件打包
  • 另一種就是每一個文件都單獨打包成一個文件的
  • 下面就來看看這兩種方式的寫法

let path = require('path');

module.exports = {
    // 1.寫成數組的方式就可以打出多入口文件,不過這里打包后的文件都合成了一個
    // entry: ['./src/index.js', './src/login.js'],
    // 2.真正實現多入口和多出口需要寫成對象的方式
    entry: {
        index: './src/index.js',
        login: './src/login.js'
    },
    output: {
        // 1. filename: 'bundle.js',
        // 2. [name]就可以將出口文件名和入口文件名一一對應
        filename: '[name].js',      // 打包后會生成index.js和login.js文件
        path: path.resolve('dist')
    }
}

這時候執行npm run build后,會生成打包好的兩個js文件,如圖所示
61643d2a6c6aece36f19bf53901805efcc293ba9

文件都打包好了,但是我們在使用的時候不能在dist目錄下去創建一個html文件,然后去引用打包后的js吧,這不合理,實際開發中也不會這樣

我們需要實現html打包功能,可以通過一個模板實現打包出引用好路徑的html來

這就需要用到一個常用的插件了,html-webpack-plugin,用之前我們來安一下它



npm i html-webpack-plugin -D

因為是個插件,所以需要在config.js里引用一下的

let path = require('path');
// 插件都是一個類,所以我們命名的時候盡量用大寫開頭
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        // 添加hash可以防止文件緩存,每次都會生成4位的hash串
        filename: 'bundle.[hash:4].js',   
        path: path.resolve('dist')
    },
    plugins: [
        // 通過new一下這個類來使用插件
        new HtmlWebpackPlugin({
            // 用哪個html作為模板
            // 在src目錄下創建一個index.html頁面當做模板來用
            template: './src/index.html',
            hash: true, // 會在打包好的bundle.js后面加上hash串
        })
    ]
}

通過上面的配置后,我們再npm run build打包看一下現在是個什么樣子了
1181ee891054d79c6600748a5674bc39a3f73c20

多頁面開發,怎么配置多頁面

如果開發的時候不只一個頁面,我們需要配置多頁面,那么需要怎么來搞呢?不用擔心,html-webpack-plugin插件自有辦法,我們來觀望一下


let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    // 多頁面開發,怎么配置多頁面
    entry: {
        index: './src/index.js',
        login: './src/login.js'
    },
    // 出口文件  
    output: {                       
        filename: '[name].js',
        path: path.resolve('dist')
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',   
            filename: 'index.html',
            chunks: ['index']   // 對應關系,index.js對應的是index.html
        }),
        new HtmlWebpackPlugin({
            template: './src/login.html',
            filename: 'login.html',
            chunks: ['login']   // 對應關系,login.js對應的是login.html
        })
    ]
}

繼續npm run build看打包后的樣子

916780b93780596501d771b8d664b79bff90e446

上面基本介紹完了html和js的打包配置了,現在我們還缺一個好兄弟css,webpack對css的解析需要用到loader,所以我們先提前安裝好,待會好方便使用

可以在src/index.js里引入css文件,到時候直接打包到生產目錄下

需要下載一些解析css樣式的loader


npm i style-loader css-loader -D
// 引入less文件的話,也需要安裝對應的loader
npm i less less-loader -D

下面我們來看一下如何配置css文件的解析

// index.js
import './css/style.css';   // 引入css
import './less/style.less'; // 引入less

console.log('這里是打包文件入口-index.js');

// webpack.config.js
module.exports = {
    entry: {
        index: './src/index.js'
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve('dist')
    },
    module: {
        rules: [
            {
                test: /\.css$/,     // 解析css
                use: ['style-loader', 'css-loader'] // 從右向左解析
                /* 
                    也可以這樣寫,這種方式方便寫一些配置參數
                    use: [
                        {loader: 'style-loader'},
                        {loader: 'css-loader'}
                    ]
                */
            }
        ]
    }
}

3761030e9477e61912a05829c2ff2d2c5805d562
  • 此時打包后的css文件是以行內樣式style的標簽寫進打包后的html頁面中,如果樣式很多的話,我們更希望直接用link的方式引入進去,這時候需要把css拆分出來
  • extract-text-webpack-plugin插件相信用過的人都知道它是干什么的,它的功效就在于會將打包到js里的css文件進行一個拆分

拆分CSS


// @next表示可以支持webpack4版本的插件
npm i extract-text-webpack-plugin@next -D
復制代碼let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
// 拆分css樣式的插件
let ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        filaneme: 'bundle.js',
        path: path.resolve('dist')
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ExtractTextWebpackPlugin.extract({
                    // 將css用link的方式引入就不再需要style-loader了
                    use: 'css-loader'       
                })
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
        }),
        // 拆分后會把css文件放到dist目錄下的css/style.css
        new ExtractTextWebpackPlugin('css/style.css')  
    ]
}

此時拆分完css后,打包的html頁面就以link的方式去引入css了,這樣很好
0cda337823dce2eb075b502d2b77d9a602b47a3c
當然大家很多都說另外一個插件也是可以辦到的,那就是mini-css-extract-plugin,是的可以說它是為webpack4而生的,而之所以上來就沒有介紹是因為還不成熟,還有很多bug需要去解決的

不過既然大家都知道它,那就順便也提一下吧


npm i mini-css-extract-plugin -D

使用起來和上面的插件是差不多的


let MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/a.css'   // 指定打包后的css
        })
    ]
}

拆分成多個css

這里要著重說一下上面兩個插件的區別了,我個人還是建議用extract-text-webpack-plugin的,畢竟從之前的版本承接下來的,雖然在安包的時候需要@next,但是還是值得信賴的

而且現在的extract-text-webpack-plugin也支持了拆分成多個css,而目前mini-css-extract-plugin還不支持此功能



// 正常寫入的less
let styleLess = new ExtractTextWebpackPlugin('css/style.css');
// reset
let resetCss = new ExtractTextWebpackPlugin('css/reset.css');

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: resetCss.extract({
                    use: 'css-loader'
                })
            },
            {
                test: /\.less$/,
                use: styleLess.extract({
                    use: 'css-loader'
                })
            }
        ]
    },
    plugins: [
        styleLess,
        resetCss
    ]
}

通過這樣操作后可以打包成兩個不同的css文件,如下圖

855d266e0c0e4820469fdebf04d5b3b9ccdf796f

引用圖片

  • 處理圖片方面,也需要loader

npm i file-loader url-loader -D

如果是在css文件里引入的如背景圖之類的圖片,就需要指定一下相對路徑

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ExtractTextWebpackPlugin.extract({
                    use: 'css-loader',
                    publicPath: '../'
                })
            },
            {
                test: /\.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192,    // 小于8k的圖片自動轉成base64格式,并且不會存在實體圖片
                            outputPath: 'images/'   // 圖片打包后存放的目錄
                        }
                    }
                ]
            }
        ]
    }
}

在css中指定了publicPath路徑這樣就可以根據相對路徑引用到圖片資源了,如下圖所示
1c3736bfdbd8d433834c6e30077ed4d49b69b756

頁面img引用圖片

頁面中經常會用到img標簽,img引用的圖片地址也需要一個loader來幫我們處理好


npm i html-withimg-loader -D
module.exports = {
    module: {
        rules: [
            {
                test: /\.(htm|html)$/,
                use: 'html-withimg-loader'
            }
        ]
    }
}


這樣再打包后的html文件下img就可以正常引用圖片路徑了

5e79d8f9f7c79fd22a7ab6e2133d5d820c7f5bf6

引用字體圖片和svg圖片

字體圖標和svg圖片都可以通過file-loader來解析


module.exports = {
    module: {
        rules: [
            {
                test: /\.(eot|ttf|woff|svg)$/,
                use: 'file-loader'
            }
        ]
    }
}

這樣即使樣式中引入了這類格式的圖標或者圖片都沒有問題了,img如果也引用svg格式的話,配合上面寫好的html-withimg-loader就都沒有問題了

通過postcss中的autoprefixer可以實現將CSS3中的一些需要兼容寫法的屬性添加響應的前綴,這樣省去我們不少的時間

由于也是一個loader加載器,我們也需要先安裝一下


npm i postcss-loader autoprefixer -D

安裝后,我們還需要像webpack一樣寫一個config的配置文件,在項目根目錄下創建一個postcss.config.js文件,配置如下:

module.exports = {
    plugins: [require('autoprefixer')]  // 引用該插件即可了
}

然后在webpack里配置postcss-loader

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader', 'postcss-loader']
            }
        ]
    }
}

在實際開發中,我們在大量的使用著ES6及之后的api去寫代碼,這樣會提高我們寫代碼的速度,不過由于低版本瀏覽器的存在,不得不需要轉換成兼容的代碼,于是就有了常用的Babel了

Babel會將ES6的代碼轉成ES5的代碼

那么不再多說,既然要使用它,就先來安一下


npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 -D

當把這些都安好后,我們就開始配置,由于要兼容的代碼不僅僅包含ES6還有之后的版本和那些僅僅是草案的內容,所以我們可以通過一個.babelrc文件來配置一下,對這些版本的支持


// .babelrc
{
    "presets": ["env", "stage-0"]   // 從右向左解析
}

我們再在webpack里配置一下babel-loader既可以做到代碼轉成ES5了


module.exports = {
    module: {
        rules: [
            {
                test:/\.js$/,
                use: 'babel-loader',
                include: /src/,          // 只轉化src目錄下的js
                exclude: /node_modules/  // 排除掉node_modules,優化打包速度
            }
        ]
    }
}

在我們每次npm run build的時候都會在dist目錄下創建很多打好的包,如果積累過多可能也會混亂

所以應該在每次打包之前將dist目錄下的文件都清空,然后再把打好包的文件放進去

這里提供一個clean-webpack-plugin插件


npm i clean-webpack-plugin -D
復制代碼let CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
    plugins: [
        // 打包前先清空
        new CleanWebpackPlugin('dist')  
    ]
}

啟動一個靜態服務器,默認會自動刷新,就是說你對html,css,js文件做了修改并保存后,瀏覽器會默認刷新一次展現修改后的效果

正常情況下我們都是在開發環境中開發項目,所以之前配置的腳本"dev"可以派上用場了,在執行npm run dev命令后,會啟動靜態服務器,我們訪問localhost:3000端口就可以看到開發的頁面內容了

如果devServer里open設為true后,會自動打開瀏覽器



module.exports = {
    devServer: {
        contentBase: './dist',
        host: 'localhost',      // 默認是localhost
        port: 3000,             // 端口
        open: true,             // 自動打開瀏覽器
        hot: true               // 開啟熱更新
    }
}

當然在npm run dev命令下,打包的文件存在于內存中,并不會產生在dist目錄下

熱更新和自動刷新的區別

在配置devServer的時候,如果hot為true,就代表開啟了熱更新

But這并沒那么簡單,因為熱更新還需要配置一個webpack自帶的插件并且還要在主要js文件里檢查是否有module.hot

下面就讓我們直接看下代碼是如何實現的



// webpack.config.js
let webpack = require('webpack');

module.exports = {
    plugins: [
        // 熱更新,熱更新不是刷新
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
        contentBase: './dist',
        hot: true,
        port: 3000
    }
}


// 此時還沒完雖然配置了插件和開啟了熱更新,但實際上并不會生效

// index.js
let a = 'hello world';
document.body.innerHTML = a;
console.log('這是webpack打包的入口文件');

// 還需要在主要的js文件里寫入下面這段代碼
if (module.hot) {
    // 實現熱更新
    module.hot.accept();
}

以上index.js中的內容,如果將變量a的值進行修改保存后,會在不刷新頁面的情況下直接修改掉,這樣就實現了熱更新

那么熱更新從現在看來和自動刷新瀏覽器的區別也不是太大嘛!自動刷新也是可以接受的啊

其實不然,熱更新的好處可能在vue或者react中有更大的發揮,其中某一個組件被修改的時候就會針對這個組件進行熱更新了,這里用到vue或react的同學去實際體驗一下吧

在webpack的配置中,resolve我們常用來配置別名和省略后綴名


module.exports = {
    resolve: {
        // 別名
        alias: {
            $: './src/jquery.js'
        },
        // 省略后綴
        extensions: ['.js', '.json', '.css']
    },
}

這個配置在webpack中比較簡單,我們也就不再敘述了,下面來看點干貨

在webpack4之前,提取公共代碼都是通過一個叫CommonsChunkPlugin的插件來辦到的。愛掏網 - it200.com到了4以后,內置了一個一模一樣的功能,而且起了一個好聽的名字叫“優化”

下面我們就來看看如何提取公共代碼


// 假設a.js和b.js都同時引入了jquery.js和一個寫好的utils.js
// a.js和b.js
import $ from 'jquery';
import {sum} from 'utils';

那么他們兩個js中其中公共部分的代碼就是jquery和utils里的代碼了

可以針對第三方插件和寫好的公共文件


module.exports = {
    entry: {
        a: './src/a.js',
        b: './src/b.js'
    },
    output: {
        filename: '[name].js',
        path: path.resolve('dust')
    },
    // 提取公共代碼
+   optimization: {
        splitChunks: {
            cacheGroups: {
                vendor: {   // 抽離第三方插件
                    test: /node_modules/,   // 指定是node_modules下的第三方包
                    chunks: 'initial',
                    name: 'vendor',  // 打包后的文件名,任意命名    
                    // 設置優先級,防止和自定義的公共代碼提取時被覆蓋,不進行打包
                    priority: 10    
                },
                utils: { // 抽離自己寫的公共代碼,utils這個名字可以隨意起
                    chunks: 'initial',
                    name: 'utils',  // 任意命名
                    minSize: 0    // 只要超出0字節就生成一個新包
                }
            }
        }
+   },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'a.html',
            template: './src/index.html',  // 以index.html為模板
+           chunks: ['vendor', 'a']
        }),
        new HtmlWebpackPlugin({
            filename: 'b.html',
            template: './src/index.html',  // 以index.html為模板
+           chunks: ['vendor', 'b']
        })
    ]
}

通過以上配置,可以把引入到a.js和b.js中的這部分公共代碼提取出來,如下圖所示

975ac394b68ea405d4ce84519db32be522fa257c

指定webpack配置文件

在package.json的腳步里,我們可以配置調用不同的webpack配置文件進行打包,舉個栗子

f364b1599318f8d009bcfbe886e5f54f838839f7

這樣的好處在于可以針對不同的需求進行一個特定的打包配置

關于webpack4的一些常規操作就說到這里了,其實在工作當中更多時候,也并不需要我們去配置這些內容

不過我們要爭做優秀的前端兒,所以就必須掌握這些必備的技能,必須會,沒有之一!

好了,就寫到這里吧,想必大家也看累了吧,辛苦大家了,哈哈。愛掏網 - it200.com




原文發布時間為:2024年04月27日
原文作者:chenhongdong
本文來源:?掘金?如需轉載請聯系原作者

聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
發表評論
更多 網友評論0 條評論)
暫無評論

返回頂部

主站蜘蛛池模板: 国产精品久久久久久一区二区三区 | 一级做a爰片久久毛片一| 老子的大ji巴cao死你| 成人精品一区二区三区中文字幕| 制服丝袜日韩中文字幕在线| 99精品视频在线观看| 国产4tube在线播放| 欧美黄色片免费观看| 国产精品久久久久久一区二区三区 | 国产伦精品一区二区三区四区| 中文字幕黄色片| 男女交性特一级| 国产精品大尺度尺度视频| 交性大片欧美网| 香蕉视频在线免费看| 日本人内谢69xxxx| 免费黄网在线观看| 2018天天操夜夜操| 日本妈妈xxxxx| 俄罗斯一级成人毛片| 尹人久久久香蕉精品| 日本欧美视频在线| 免费国产黄网站在线观看视频| 1313苦瓜网在线播| 日本大片免a费观看视频| 免费成人在线观看| www视频在线观看免费| 我叫王筱惠第1部分阅读| 亚洲综合AV在线在线播放| 久久精品老司机| 少妇人妻在线视频| 亚洲天天做日日做天天看| 蜜桃成熟时2005| 在线观看一二三区| 久久综合色视频| 男男gay做爽爽视频| 国产白嫩美女在线观看| 两根黑人粗大噗嗤噗嗤视频| 欧美日韩一区二区三区麻豆| 国产亚洲精品bt天堂精选| aa级女人大片喷水视频免费|