帶你由淺入深探索webpack4(一)


 相信你或多或少也聽說過webpack、gulp等這些前端構建工具。近年來webpack越來越火,可以說成為了前端開發者必備的工具。如果你有接觸過vue或者react項目,我想你應該對它有所了解。

這幾天我重新整理了一下webpack中知識點,把一些常用到的總結出來,希望能幫助到大家以及加深自己對webpack的理解。

(由於我在寫這篇文章的時候webpack最新版本是4.3 如果某些配置有變更,請自行查看官方最新文檔。千萬別看中文文檔,坑太多了更新太慢,很多屬性都被棄用了,要看直接看英文的。)

 

一: 初識webpack

1.1 什么是webpack?

這個我直接引用官方文檔的介紹:

Webpack 是當下最熱門的前端資源模塊化 管理和打包 工具。它可以將許多松散的模塊按照依賴和規則打包成符合生產環境部署的前端資源。還可以將按需加載的模塊進行代碼分割,等到實際需要的時候再異步加載。

在這里我就不多介紹了,百度一搜一大堆介紹,本文章主要是介紹webpack怎么用。

 

1.2 安裝webpack

因為webpack是基於nodejs實現的,所以要安裝webpack,先得安裝node

nodejs的中文網址:http://nodejs.cn/

下載完node之后,直接傻瓜式安裝就好,接着,我們打開命令行,看下node和vue的版本

當輸出版本號時,證明安裝成功。(建議node盡量8.0版本以上 npm盡量6.0版本以上)。

這里我比較建議用淘寶的鏡像cnpm,npm在國內實在是太慢了。

npm install -g cnpm --registry=https://registry.npm.taobao.org

當然,如果你網速快的話,用npm命令也沒關系。

首先,我們創建一個空的文件夾,就起名叫webpack吧,然后執行一下初始化命令

npm init -y

接着安裝webpack和webpack-cli(建議局部安裝,全局安裝webpack可能會導致webpack版本不同而無法正常使用)

npm install webpack webpack-cli --save-dev 或者 cnpm install webpack webpack-cli -save-dev

 

 

1.3 webpack的初始化配置

首先我們在本件的一級目錄下創建一個src文件,src文件夾內再創建一個inde.js文件和一個index.html文件

src/html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>初始化配置</title>
</head>
<body>
<div id="root">hello word!</div>
<script src="index.js"></script>
</body>
</html>
 

src/js:

var root = document.getElementById('root');
var text = document.createElement('div');
text.innerText = "斌果歡迎你!"
root.append(text);

當然packagej.json文件也要配置一下。

刪除“main”入口配置添加"private"為true

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "private":true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0"
  }
}

這樣做主要是為了讓你的項目私有化,防止意外發布你的代碼。

接着,在一級目錄下再創建一個 webpack.config.js  這個主要是webpack的配置文件

webpack.config.js

const path = require('path');

module.exports = {
    entry:'./src/index.js',  //打包文件的入口
    output:{                 //打包文件的出口
        filename:'bundle.js',          //打包后的文件名
        path:path.resolve(__dirname,'dist')      //打包后文件存放的位置
    }
}

webpack使用的是common.js規范的語法,在webpack.config.js中設置了webpack打包的基本配置。

接着我們在控制台中直接運行

npx webpack

 再回到項目中的,發現多了一個dist文件夾。里面有一個打包后的bundle.js文件,就這樣我們就將這個簡單的項目打包成功了。

你或許會問npx是什么,我怎么從來沒有用過,可能你一直都是在用npm run **  npx其實就是直接運行node_modules中的配置

當然你也可以在package.json中配置一下,像這樣

配置之后你運用npm run bundle 效果其實和運行 npx webpack是一樣,其最終還是運行npx webpack的命令.。

 

1.4 webpack的初次使用

在上一小節,你可能會覺得,這webpack打包完后好像也並沒有用,到底webpack是用來干嘛的?這一小節,就帶你用用webpak。

繼續上一節,我們在src下繼續創建header.js,connent.js、footer.js這三個文件.。

src/header.js

var root = document.getElementById('root');
var text = document.createElement('div');
text.innerText = "頭部內容"
root.append(text);

src/content.js

var root = document.getElementById('root');
var text = document.createElement('div');
text.innerText = "中部內容"
root.append(text);

src/footer.js

var root = document.getElementById('root');
var text = document.createElement('div');
text.innerText = "尾部內容"
root.append(text);

如果我們想將這三個js同時引入到index.html我們就必須要這樣寫

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>簡單實例</title>
</head>
<body>
    <div id="root">hello word!</div>
    <script src="header.js"></script>
    <script src="content.js"></script> 
    <script src="footer.js"></script>
</body>
</html>

這樣我們要引入3個js  對性能的消耗是十分巨大的 ,加入有100個這樣的js文件,那我們不就要引入100個js?  於是我們想可以可以只引入一個inde.js。就像下面那樣:

我們將src中引入的header、content、footer、index全部使用esModule語法如下

function header(){
    var root = document.getElementById('root');
    var text = document.createElement('div');
    text.innerText = "頭部內容"
    root.append(text);
}
export default header;
import header from './header'
import content from './content'
import footer from './footer'

header();
content();
footer();

當我們打開html,就會發現報了個錯!

這是為什么呢?  因為瀏覽器根本都不認識import是什么,是不認識es、common這些語言的,但是,webpack認識啊!

我們直接運行     npx webpack

然后我們index.html中直接引入打包后的bundle.js,就會神奇的發現他成功運行而且沒報錯。

因為webpack已經幫我們將esModule語法轉化為瀏覽器能識別的法語告訴瀏覽器我要引入這三個js。

 

 

 

二、webpack的核心常用配置

 

2.1 HtmlWebpackPlugin

在上一章可以看到,當我們打包完成后,要自己將打包后的js代碼引入到html文件中,這顯得不那么智能。

HtmlWebpackPlugin插件做得工作就是在打包完成后,自動生成一個html文件,並將打包生成的js自動引入到html文件中。

首先安裝這個插件:  npm install html-webpack-plugin -D

安裝完成后,我們需要在webpack.config.js中配置一下:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');  //++++導入插件

module.exports = {
    entry:'./src/index.js',  //打包文件的入口
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //++++其會根據該html文件作模板自動導入打包后的js ,然
        })                               //++++后將生成的html放到出口文件夾中
    ],                             
    output:{                 //打包文件的出口
        filename:'bundle.js',          //打包后的文件名
        path:path.resolve(__dirname,'dist')      //打包后文件存放的位置
    }
}

這樣的話就無需要我們自己配置html  其會在出口文件夾自動生成打包后的html。

運行npx webpack后

=>

 

 

2.2 CleanWebpackPlugin

當我們每次打包完文件后,都會生成一個新的dist文件覆蓋上一個dist文件,但如果上個dist中有一些其他的文件沒有被覆蓋掉,就會成為雜魚,當我們多次打包后,雜魚可能就會變得越來越多,嚴重影響開發。

CleanWebpackPlugin插件做得就是每次打包時都會刪除上一次打包的文件,而不是覆蓋,這就使得每一次打包后的文件都是嶄新的,而不會混合上一次遺留的文件。

首先安裝這個插件: npm install clean-webpack-plugin -D

接着配置一下webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');  //++++導入插件

module.exports = {
    entry:'./src/index.js',  //打包文件的入口
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //其會根據該html文件作模板自動導入打包后的js ,然
        }),                             //后將生成的html放到出口文件夾中
        new CleanWebpackPlugin()    //++++配置刪除的文件                              
    ],                             
    output:{                 //打包文件的出口
        filename:'bundle.js',          //打包后的文件名
        path:path.resolve(__dirname,'dist')      //打包后文件存放的位置
    }
}

運行npx webpack 后

 =>

 

 

 2.3 Mode配置

當我們每次打包的時候都會提示如下警告 

這到底是什么呢? 其實就是叫我們設置工作狀態,既mode

mode有兩種狀態,主要是用於表明當前開發狀態!

development: 開發模式    打包后代碼沒有被壓縮

production:    生產模式     打包后代碼被壓縮為一行

 

 

2.4 SourceMap配置

當我們的代碼報錯時,調試工具顯示的是打包后js的報錯行數,這樣我們很難找到原代碼到底在哪報錯。

SourceMap主要用於開發模式下使用,其能展現出打包后文件與源文件的映射關系。

這到底是怎么用的呢? 查看下官方文檔可以看到有這么多參數,不急,慢慢來解釋:

 

+表示性能較好,-表示性能較差  eval、inline、cheap、module等可以自由組合使用

none:不產生映射,速度最快。

eval:執行速度也很快,性能最好,當時代碼提示不全面。

source-map:  把映射文件生成到獨立的文件,一般不建議使用,打包速度過慢。

-inline-: 不單獨生成文件,將生成的映射文件以base64的格式插入到打包后的js文件中,精確顯示錯誤位置

-cheap-:代碼只顯示出錯代碼在第幾行,不精確顯示具體位置,有效提高打包效率。

-module-:不僅提示自己的業務代碼是否出錯,還提示第三方模塊中的代碼是否出錯。

在開發環境中,建議使用:cheap-module-eval-source-map 

在生產環境中,上線代碼一般不設置devtool。如果想知道報錯位置,建議使用:cheap-module-source-map

因為我們主要在開發環境下,所以我們使用cheap-module-eval-source-map

 

 

 2.5資源管理配置

2.5.1 加載css、sass、css前綴

首先我們先在src下創建一個index.css

src/index.css:

body{
    background-color: blue;
}

接着我們在src中的index.js中導入css文件

src/index.js:

import header from './header'
import content from './content'
import footer from './footer'
import './index.css'    //+++引入css文件

header();
content();
footer();

由於webpack是無法識別以css后綴的文件,所以我們要引入loader(翻譯官)幫我們解析css.

我們需要安裝一下loader:  npm install style-loader css-loader --save-dev

安裝完成后,我們還需要在webpack.config.js中配置一下:

webpack.config.js:

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',   //+++映射
    entry:'./src/index.js',  //打包文件的入口
    module:{
        rules:[
            {
                test:/\.css$/,       //+++配置以css結尾的文件  
                use:[                //+++添加翻譯官,順序為由下向上,由右向左
                    'style-loader',
                    'css-loader'
                ]
            }          
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //其會根據該html文件作模板自動導入打包后的js ,然
        }),                             //后將生成的html放到出口文件夾中
        new CleanWebpackPlugin()    //配置刪除的文件                              
    ],                             
    output:{                 //打包文件的出口
        filename:'bundle.js',          //打包后的文件名
        path:path.resolve(__dirname,'dist')      //打包后文件存放的位置
    }
}

由於css翻譯官解析后webpack還是不認識css文件,還需要使用style翻譯官去處理一下才能被webpack所解析。

運行npx webpack打包后,我們直接打開dist下的index.html文件,就可以看到css文件已經被成功引入.

加載sass也是類似,只需要添加一個sass-loader、node-sass就可以了!在這里就不加演示。

{
                test:/\.scss$/,
                use:[
                    'style-loader',
                    'css-loader',
                    'sass-loader'
                ]
            }        

而加前綴的話,在不同瀏覽器前綴各有不同。

  • Trident內核:主要代表為IE瀏覽器, 前綴為-ms
  • Gecko內核:主要代表為Firefox, 前綴為-moz
  • Presto內核:主要代表為Opera, 前綴為-o
  • Webkit內核:產要代表為Chrome和Safari, 前綴為-webkit

在這里我們只需要引入postcss-loader和autoprefixer就可以了

安裝一下 : npm install postcss-loader autoprefixer --save-dev

在根目錄下創建一個postcss.config.js文件

postcss.config.js:

module.exports = {
    plugins:[
        require('autoprefixer')
    ]
}

接着在webpack.config.js修改一下loader

           {
                test:/\.css$/,       //配置以css結尾的文件  
                use:[                //添加翻譯官,順序為由下向上,由右向左
                    'style-loader',
                    'css-loader',
                    'postcss-loader'       //+++配置前綴
                ]
            },
            {
                test:/\.scss$/,
                use:[
                    'style-loader',
                    'css-loader',
                    'sass-loader',   //配置sass翻譯官
                    'postcss-loader'   //+++配置前綴
                ]
            }      

但是如果我們要在sass中再引入sass 這就會出錯,因為再引入的sass文件沒有經過翻譯官翻譯.

所以,我們還需要配置一下sass

           {
                test:/\.scss$/,
                use:[
                    'style-loader',
                    {
                        loader:'css-loader',
                        options:{
                            importLoader:2,//+++如果sass文件還引入其他sass,另一個會重新從下向上開始解析
                            modules:true //+++開啟css模塊打包
                        }
                    },
                    'sass-loader',          //配置sass翻譯官
                    'postcss-loader'        //配置前綴
                ]
            }   

2.5.2 加載圖片、字體

加載圖片主要使用兩個loader分別為 file-loader  url-loader

其兩個loader都是解析圖片。不過url-loader可以將小圖片轉化成base64的格式存放到打包后的css中

我們一般都是使用url-loader 這樣處理小圖片的時候就可以更快加載而無需引用原圖片地址。

安裝: npm install url-loader file-loader -D

配置:

webpack.config.js:

          {
                test:/\.(png|jpg|gif|svg)$/,
                use:[
                    {
                        loader:'url-loader',
                        options:{
                            name:'[name].[ext]',
                            outputPath:'images/',
                            limit:8096  //+++小於4K的圖片轉化為base64存放到打包后的js中
                        }
                    }
                ]

            }        

因為file-loader和url-loader可以加載任何文件,所以我們也可以用其來加載字體文件

webpack.config.js:

           {
                test:/\.(woff|woff2|eot|ttf|otf)&/,
                use:[
                    'file-loader'
                ]

            }

 2.5.3加載es6語法

由於很多低版本的瀏覽器都不支持ES6語法,所以,我們需要將ES6語言轉換為ES5的語法。

在以前我都是用babel-preset-es2015轉換的,現在官方推薦使用babel-preset-env轉換,我們就使用官方推薦的來轉換吧.

由於babel只轉換語法,需要使用babel-polyfill來支持新語法像promise這些。

首先我們先安裝依賴  npm install babel-loader @babel/core babel-preset-env @babel/polyfill -D

接着我們在webpack.config.js中配置一下

webpack.config.js:

{
                test: /\.js$/,
                exclude: /node_modules/,//不需要對第三方模塊進行轉換,耗費性能
                use:[
                    'babel-loader'
                ] 
       

            },

因為bebel配置的信息太多了,我們可以在根目錄下創建一個.babelrc文件

.babelrc:

{
    "presets": [
        [
            "babel-preset-env", {         
                "targets": {         //在這些版本以上的瀏覽器中不轉換為es5
                    "chrome": "67",
                    "firfox":"60",
                    "edge":"17",
                    "safari":"11.1"
                },
                "useBuiltIns": "usage"
            }
        ]
    ]
}

最后我們還需要在index.js中引入polyfill:

src/index.js:

import "@babel/polyfill";

但是如果在第三方模塊時使用@babel/polyfill會污染全局變量,所以我們可以使用runtime-transform插件

其與polifill類似,但不會污染全局變量其用法和上面差不多

我們安裝一下:

npm install babel-runtime babel-plugin-transform-runtime -D

在.babelrc中添加配置就可以了。

{
    "plugins": ["transform-runtime"]
}

更多的配置可以參考官網文檔:babeljs.io/setup

 

 

2.6配置多個出入口文件

在目前,我們一直以一個index.js為入口,bundle.js文件為出口,但隨着程序的增加,我們可能需要輸出多個bundle文件。

這個很簡單,我們新建一個print.js文件,並添加一些邏輯

import Header from './header'

Header();
console.log('這是打包的第二入口文件');

然后我們只需要修改一下webpack.config.js中的出入口配置就可以了。

webpack.config.js:

 entry:{
        main:'./src/index.js',       //打包入口文件
        print:'./src/print.js'
    },
......
 output:{
       filename:'[name].js',          //打包后的文件名
        path:path.resolve(__dirname,'dist')      //打包后文件存放的位置
     }

 

 

2.7熱更新配置

我們每次打包的時候,都需要手動運行npm run bundle 或者npx webpack這顯得什么繁瑣。

下面介紹幾個配置,可以在代碼發生變化后自動編譯代碼。

2.7.1觀察模式watch

我們只需要在package.json文件中添加一個用於啟動觀察模式的npm script腳本就可以了;

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "bundle": "webpack",
    "watch": "webpack --watch"    //+++添加啟動腳本
  },
   "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.5.1",
    "clean-webpack-plugin": "^2.0.1",
    "css-loader": "^2.1.1",
    "file-loader": "^3.0.1",
    "html-webpack-plugin": "^3.2.0",
    "node-sass": "^4.11.0",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "url-loader": "^1.1.2",
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0"
  }
}

這樣當我們修改js中的代碼時,其會自動執行打包,我們只需要刷新一下頁面就可以看到變化。

2.7.2使用webpack-dev-server

當我們使用watch時,我們雖然可以自動打包,但是頁面不能自動刷新,需要我們手動刷新。

webpack-dev-server為我們提供了一個簡單的web服務器,能夠實時重新加載。

我們首先需要安裝一下: npm install webpack-dev-server -D

接着我們需要修改webpack.config.js配置,告訴服務器,在哪里查找文件。

webpack.config.js:

......

module.exports = {
    mode:'development',
    devtool:'cheap-module-eval-source-map',   //映射
    entry:{                     //配置入口文件
        main:'./src/index.js',
        print:'./src/print.js'
    },
    devServer:{
        contentBase:'./dist',      //+++配置運行目錄
        open:true,                 //+++自動打開瀏覽器
        port:8080,                 //+++服務器訪問端口
        proxy:{                    //+++配置跨越代理
            'api':'http://loacalhost:3000'
        }
    },
   ......
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //其會根據該html文件作模板自動導入打包后的js ,然
        }),                             //后將生成的html放到出口文件夾中
        new CleanWebpackPlugin()    //配置刪除的文件                              
    ],                             
    output:{                 //打包文件的出口
        filename:'[name].js',          //打包后的文件名
        path:path.resolve(__dirname,'dist')      //打包后文件存放的位置
    }
}

然后我們只需要在package.json中添加一個script腳本用於啟動即可,

 "scripts": {
    "bundle": "webpack",
    "watch": "webpack --watch",
    "server": "webpack-dev-server"    //+++啟動wepack-dev-server
  },

運行npm webpack server 就可以看到webpack已經啟動了一個服務器。

2.7.3使用webpack-dev-middleware

webpack-dev-middleware是一個容器,它可以吧webpack處理后的文件傳遞給一個服務器。webpack-dev-server在內部就是使用了它。

這個僅僅了解就可以了,沒必要自己寫一個server,且性能沒有webpack-dev-server好。這里主要是配合express server來使用

首先我們自己安裝一下:npm install express webpack-dev-middleware --save-dev

然后我們需要在webpack.config.js中配置一下

output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
      publicPath: '/'      //+++
    }

接着我們需要創建一個server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath
}));

// Serve the files on port 3000.
app.listen(3000, function () {
  console.log('Example app listening on port 3000!\n');
});

這時我們只需要在package.json中添加一個srcipt腳本然后直接運行腳本就可以了

"server": "node server.js",

 

 

2.8模塊熱替換(HMR)

當我們啟動server時,如果修改某個模塊,它就會整個網頁重新刷新,之前的操作又得重來。

HMR就是允許運行時更新各種模塊,而不用完全刷新。也就是只更新有變動的模塊,其他模板不動。

注:HMR只適合在開發環境下,並不適合在線上環境下配置。

因為HMR是webpack內置的插件,所以無需再下載,在使用之前,我們先將print.js刪除。再引入HMR的相關配置。

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');  //導入插件
const webpack = require('webpack');     //+++導入webpack

module.exports = {
    mode:'development',
    devtool:'cheap-module-eval-source-map',   //映射
    entry:{                     //配置入口文件
        main:'./src/index.js'
    },
    devServer:{
        contentBase:'./dist',      //配置運行目錄
        open:true,                 //自動打開瀏覽器
        port:8080,                 //服務器訪問端口
        proxy:{                    //配置跨越代理
            'api':'http://loacalhost:3000'
        },
        hot:true,              //+++開啟熱更新
        hotOnly:true            //+++即使html錯誤,也不讓頁面更新,           
    },
    ......
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //其會根據該html文件作模板自動導入打包后的js ,然
        }),                             //后將生成的html放到出口文件夾中
        new CleanWebpackPlugin(),    //配置刪除的文件    
        new webpack.NamedModulesPlugin(),        //+++以便更容易查看要修補(patch)的依賴
        new webpack.HotModuleReplacementPlugin()      //+++使用模塊熱替換插件
    ],                             
    output:{                 //打包文件的出口
        filename:'[name].js',          //打包后的文件名
        path:path.resolve(__dirname,'dist')      //打包后文件存放的位置
    }
}

到這里還沒有完  要想實現熱替換,還要配置一下index.js

import header from './header'
import content from './content'
import footer from './footer'
import './index.css'    //引入css文件

header();
content();
footer();

//如果模塊啟用了HMR,就可以用 module.hot.accept(),監聽模塊的更新。
if (module.hot) {
    module.hot.accept('./header.js', function() {
       header()
    })
  }
  

當我們單修改header.js時,其他模塊並不會影響,只會更新header模塊的內容。但我們會發現修改header會創建一個新的dom。

這是因為我們每次更新header模塊都創建了一個dom 我們需要先修改一下js代碼在更新前先清除之前添加的dom節點。

所以在使用HMR時要根據不同的代碼做相應的設置。

HMR修改樣式表

這個就更簡單了,其實在上面我們應該實現了這個功能,無須做任何修改,當我們修改css樣式時,其他模塊是不會刷新的。無需設置module.hot.accept。

因為style-loader已經幫我們在后台使用 module.hot.accept 來修補(patch) <style> 標簽。

 

 

2.9 tree shaking

在我們編寫代碼時或引入第三方庫的時候,很多時候會引入很多冗余的代碼,不經意間增大了性能的消耗。

tree shaking是一個術語,通常用於描述移除JavaScript上下問中未引用的代碼,其只支持es6模塊例如import和export。

實現這個功能很簡單,只需要在package.json中配置“sideEffects”屬性就能實現。

"sideEffects":["*.css"],   //+++對所有css不使用Tree shaking。

如果將其設置為false則對所有使用tree shaking。如果不想怕誤刪的文件可以寫在數組里。

在生產環境中,其會自動壓縮打包,無需設置optimization,如果在開發環境中還是要配置一下的。

webpack.config.js:

......
module.exports = { mode:'development', devtool:'cheap-module-eval-source-map', //映射 entry:{ //配置入口文件 main:'./src/index.js' }, ...... optimization:{ //+++在開發環境中配置,生產環境不用 usedExports:true }, output:{ //打包文件的出口 filename:'[name].js', //打包后的文件名 path:path.resolve(__dirname,'dist') //打包后文件存放的位置  } }

 

 

2.10生產環境構建

在我們之前的開發中一直都是以開發環境開發為主,然而生產環境與開發環境有很大的區別,在開發環境中,注重的是怎樣使開發更便利,而在生產環境中注重的是如果使代碼性能更高,簡而精。所以我們很有必要將開發環境和生產環境分離出來。

在這里我們應該抽取出他們的公共部分,再將它們與公共配置分別合並在一起,這時,我們就需要一個工具:webpack-merge

首先,我們先安裝一下這個工具。

npm isntall webpack-merge -D

然后我們需要創建三個文件:webpack.common.js、webpack.dev.js、webpack.prod.js。我們將公共部分抽離到webpack.common.js中,刪除掉webpack.config.js

 webpack.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); //導入插件 const webpack = require('webpack'); //導入webpack  module.exports = { entry:{ //配置入口文件 main:'./src/index.js' }, module:{ rules:[ { test: /\.js$/, exclude: /node_modules/,//不需要對第三方模塊進行轉換,耗費性能  use:[ 'babel-loader' ] }, { test:/\.css$/, //配置以css結尾的文件 use:[ //添加翻譯官,順序為由下向上,由右向左 'style-loader', 'css-loader', 'postcss-loader' //配置前綴  ] }, { test:/\.scss$/, use:[ 'style-loader', { loader:'css-loader', options:{ importLoader:2,//如果sass文件還引入其他sass,另一個會重新從下向上解析 modules:true //開啟css模塊打包  } }, 'sass-loader', //配置sass翻譯官 'postcss-loader' //配置前綴  ] }, { test:/\.(png|jpg|gif|svg)$/, use:[ { loader:'url-loader', options:{ name:'[name].[ext]', outputPath:'images/', limit:8096 //小於4K的圖片轉化為base64存放到打包后的js中  } } ] }, { test:/\.(woff|woff2|eot|ttf|otf)&/, use:[ 'file-loader' ] } ] }, plugins:[ new HtmlWebpackPlugin({ template: 'src/index.html' //其會根據該html文件作模板自動導入打包后的js ,然 }), //后將生成的html放到出口文件夾中 new CleanWebpackPlugin() //配置刪除的文件  ], output:{ //打包文件的出口 filename:'[name].js', //打包后的文件名 path:path.resolve(__dirname,'dist') //打包后文件存放的位置  } }

webpack.dev.js:

const webpack = require('webpack');     //導入webpack
const merge = require('webpack-merge');
const common = require('./webpack.common'); module.exports = merge(common,{ mode:'development', devtool:'cheap-module-eval-source-map', devServer:{ contentBase:'./dist', //配置運行目錄 open:true, //自動打開瀏覽器 port:8080, //服務器訪問端口 hot:true //開啟熱更新  }, plugins:[ new webpack.NamedModulesPlugin(), //以便更容易查看要修補(patch)的依賴 new webpack.HotModuleReplacementPlugin() //使用模塊熱替換插件  ], optimization:{ //在開發環境中配置,生產環境不用 usedExports:true } })

webpack.prod.js:

const merge = require('webpack-merge');
const common = require('./webpack.common'); module.exports = merge(common,{ mode:'production', devtool:'cheap-module-source-map' })

 接着我們只需在package.json中配置一下script腳本,運行不同的腳本進行不同環境下的打包

package.json:

 "dev":"webpack-dev-server --config ./webpack.dev.js",   
"build":"webpack --config ./webpack.prod.js"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM