webpack4 配置(CSS变姨、靜態(tài)資源族扰、ES6 環(huán)境、開(kāi)發(fā)服務(wù)器)

本文會(huì)一步一步從 webpack 安裝定欧、npm 腳本命令添加渔呵、各個(gè)插件的作用和安裝及配置一步一步說(shuō)明,如果不想看砍鸠,可以跳到文末扩氢,我會(huì)把所有安裝的插件和配置匯總放在最后。

1. 安裝 webpack 和 webpack-cli

npm install --save-dev webpack webpack-cli

新建 src 目錄爷辱,此為源文件目錄
因?yàn)榉侨职惭b录豺,webpack 沒(méi)加入全局變量,只能通過(guò)npx執(zhí)行命令

npx webpack // npx為npm 5.2后增加的命令

打包后會(huì)生成 dist 目錄饭弓,此為打包文件的目錄

├── /項(xiàng)目目錄(根目錄)
│   ├──  /src(源文件目錄)
│          └── index.js
│   ├──  /dist(打包文件生成目錄)
│          └── main.js
│   ├──  /node_modules(包安裝目錄)
│          └── ......
│   ├──  package-lock.json
│   └──  package.json

2. 為 npm 添加命令

使用過(guò) vue.js 的腳手架 vue-cli 的話双饥,會(huì)常用到命令如:

npm run dev

其實(shí)這個(gè)是 vue-cli 在 npm 中配置好的。
package.jsonscripts 中就可以配置腳本:

  // ...
  "scripts": {
    "build": "webpack --config webpack.config.js",
  },
  //  ...

上述配置會(huì)增加一個(gè)打包命令:

npm run build

3. 配置webpack

在根目錄新建 webpack.config.js 如下:

const path = require('path')
module.exports = {
    entry: './src/index.js', //入口文件
    output: {
        filename: 'bundle.[hash].js', //默認(rèn)為main.js 
        path: path.resolve(__dirname,'./dist') //path為絕對(duì)路徑弟断,用node path模塊轉(zhuǎn)化
    },
    mode: 'development' //開(kāi)發(fā)模式
}
  • entry 為入口源文件
  • output 為打包后生成文件的設(shè)置兢哭,其中 filename 為生成的文件名,[hash]為隨機(jī)哈希字符串夫嗓,避免緩存迟螺。path 為打包文件生成的目錄。
  • mode 為打包的模式舍咖,默認(rèn)為production(生產(chǎn)模式)矩父,會(huì)壓縮代碼。development(開(kāi)發(fā)模式)不會(huì)壓縮代碼排霉,便于閱讀窍株。
  • tips:打包文件使用[hash]后,每次打包都會(huì)生成新的文件攻柠,久了會(huì)產(chǎn)生大量冗余文件球订,這個(gè)時(shí)候就需要用到 clean-webpack-plugin 來(lái)清除老版本文件。
npm i clean-webpack-plugin -D // i 等于 install, -D 等于 --save-dev

webpack.config.js 里引入

// ...
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
    // ...
    plugins:[ //存放插件
        new CleanWebpackPlugin()
    ]
}

此時(shí)的 webpack.config.js 長(zhǎng)這個(gè)樣子:

const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
    entry: './src/index.js', //入口文件
    output: {
        filename: 'bundle.[hash].js', //默認(rèn)為main.js  [hash]是為了避免js緩存
        path: path.resolve(__dirname,'./dist') //path為絕對(duì)路徑瑰钮,用node path模塊轉(zhuǎn)化
    },
    mode: 'development', //開(kāi)發(fā)模式
    plugins:[ //存放插件
        new CleanWebpackPlugin()
    ]
}

現(xiàn)在冒滩,每次打包前,都會(huì)清空 dist 目錄

4. 自動(dòng)生成 html

目前打包只能生成 js 文件浪谴,每次都還要手動(dòng)的去 html 文件中引用开睡,十分不方便因苹,如果需要自動(dòng)生成 html,則要用到 html-webpack-plugin

npm i html-webpack-plugin -D

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>
    html
</body>
</html>

webpack.config.js 里引入

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    // ...
    plugins:[
        // ...
        new HtmlWebpackPlugin({
            template: './src/index.html', // 模板位置
            filename: 'index.html', // 生成的html文件名篇恒,默認(rèn)也是index.html
            minify: {
                removeAttributeQuotes: true, // 刪除標(biāo)簽屬性的雙引號(hào)
                collapseInlineTagWhitespace: true, // 刪除多余空格
            },
            hash: true  // 增加hash扶檐,避免緩存
        })
    ]
}

現(xiàn)在,每次打包胁艰,會(huì)在 dist 目錄中生成一個(gè) index.html款筑,并自動(dòng)引入 js 文件

5. 配置本地開(kāi)發(fā)服務(wù)器

本地開(kāi)發(fā)服務(wù)器可以不用每次都打包生成文件,再去看效果:

npm i webpack-dev-server -D

webpack.config.js 里引入

    devServer:{ // 開(kāi)發(fā)服務(wù)器配置
        port: 3000, // 端口號(hào)
        progress: true, // 進(jìn)度條
        contentBase: './static', // 服務(wù)默認(rèn)指向文件夾腾么,靜態(tài)資源
        inline: true, // 設(shè)置為true醋虏,當(dāng)源文件改變的時(shí)候會(huì)自動(dòng)刷新
        historyApiFallback: true, // 在開(kāi)發(fā)單頁(yè)應(yīng)用時(shí)非常有用,它依賴于HTML5 history API哮翘,如果設(shè)置為true,所有的跳轉(zhuǎn)將指向index.html
        hot: true, // 允許熱加載
        open: true // 自動(dòng)打開(kāi)瀏覽器
    }

啟動(dòng)這個(gè)服務(wù)可以通過(guò)如下命令啟動(dòng)

npx webpack-dev-server

也可以在 package.jsonscripts 腳本配置:

  "scripts": {
    "build": "webpack --config webpack.config.js",
    "dev": "webpack-dev-server"
  }

運(yùn)行

npm run dev

則自動(dòng)在瀏覽器打開(kāi)了一個(gè)服務(wù)毛秘。
到此饭寺,目錄結(jié)構(gòu) 如下:

├── /項(xiàng)目目錄(根目錄)
│   ├──  /src(源文件目錄)
│          ├── index.html
│          └── index.js
│   ├──  /dist(打包文件生成目錄)
│          ├── index.html
│          └── bundle.2957e949a4a4bf4735f3.js
│   ├──  /node_modules(包安裝目錄)
│          └── ......
│   ├──  /static(靜態(tài)資源目錄)
│          └── ......
│   ├──  package-lock.json
│   ├──  package.json
│   └──  webpack.config.js

6. css模塊的配置

引入 css 文件,一般是在 html 中通過(guò) link 標(biāo)簽引入叫挟,或者在 js 中

require('./style.css')

因?yàn)?webpack 默認(rèn)不識(shí)別 css艰匙、less,則需要安裝各種 ** loader** :

npm i css-loader style-loader less less-loader -D

webpack.config.js 中加入 loader

// ...
module.exports = {
      // ...
    module: {
        rules: [ 
            {
                test: /\.css$/, // js 中 require css
                use: ['style-loader','css-loader']
            },
            { 
                test: /\.less$/, 
                // 注意順序抹恳!
                use: ['style-loader','css-loader','less-loader'] 
            }
        ]
    },
    plugins:[
       // 存放插件
    ],
    devServer:{
       // 開(kāi)發(fā)服務(wù)器
    }
}

7. ES6 處理

目前的瀏覽器對(duì) ES6 語(yǔ)法支持都不完整员凝,需要轉(zhuǎn)化成 ES5 才能執(zhí)行:

npm install babel-loader @babel/core @babel/preset-env -D

webpack.config.js 中加入 :

// ...
module.exports = {
      // ...
    module: {
        rules: [ 
            // ...
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                  loader: 'babel-loader',
                  options: {
                    presets: ['@babel/preset-env']
                  }
                }
            }
        ]
    },
    plugins:[
       // 存放插件
    ],
    devServer:{
       // 開(kāi)發(fā)服務(wù)器
    }
}

es6 內(nèi)置方法轉(zhuǎn)化:

npm i @babel/plugin-transform-runtime -D
npm install --save @babel/runtime @babel/polyfill  // 這個(gè)正式環(huán)境也要用

babel-runtime和babel-polyfill的作用介紹和使用
上面的 webpack.config.js 改為 :

// ...
module.exports = {
      // ...
    module: {
        rules: [ 
            // ...
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                  loader: 'babel-loader',
                  options: {
                    presets: ['@babel/preset-env'],
                    plugins:[ // es6 內(nèi)置函數(shù)轉(zhuǎn)換
                        '@babel/plugin-transform-runtime'
                    ]
                  }
                }
            }
        ]
    },
    plugins:[
       // 存放插件
    ],
    devServer:{
       // 開(kāi)發(fā)服務(wù)器
    }
}

js文件里引入:

require('@babel/polyfill')

至此,可以打包 ES6 語(yǔ)法的文件了奋献。

8. 加載圖片健霹、音頻等資源

以圖片為例,引入情況有三種:

  • css 中的背景圖片
body{
    background: url('./img/bg.jpg')
}
  • js中通過(guò)創(chuàng)建Image標(biāo)簽再引入:
import logo from './img/logo.jpg'
let img = new Image()
img.src = logo
  • 在html標(biāo)簽中引入
<img src="./img/logo.jpg" alt="">

前兩中情況瓶蚂,需要安裝:

npm i url-loader file-loader -D

webpack.config.js 加入:

// ...
module.exports = {
      // ...
    module: {
        rules: [ 
            // ...
            {
                test: /\.(png|jpe?g|gif|m4a)$/, // 加載js img 對(duì)象糖埋、css 中的圖片、音頻等資源
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            //資源大小小于等于limit值窃这,則會(huì)以base64形式加載瞳别,不會(huì)發(fā)請(qǐng)求,大于這個(gè)值則用file-loader加載
                            limit: 200*1024
                        }
                    }
                ]
            }
        ]
    },
    plugins:[
       // 存放插件
    ],
    devServer:{
       // 開(kāi)發(fā)服務(wù)器
    }
}

在html標(biāo)簽中引入圖片需要安裝:

npm i html-withimg-loader -D

webpack.config.js 加入:

// ...
module.exports = {
      // ...
    module: {
        rules: [ 
            // ...
            {
                test: /\.html$/, // 加載 img 標(biāo)簽中的圖片
                use: [
                  {
                    loader: 'html-withimg-loader',
                    options: {}
                  }
                ]
            }
        ]
    },
    plugins:[
       // 存放插件
    ],
    devServer:{
       // 開(kāi)發(fā)服務(wù)器
    }
}

匯總:

安裝的插件有:

npm i --D webpack webpack-cli clean-webpack-plugin html-webpack-plugin webpack-dev-server css-loader style-loader less less-loader babel-loader url-loader file-loader html-withimg-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime
npm i --save @babel/runtime @babel/polyfill

最后 webpack.config.js 長(zhǎng)這個(gè)樣子:

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin') // 自動(dòng)清除沉余js
const HtmlWebpackPlugin = require('html-webpack-plugin') // 自動(dòng)生成 html 插件

module.exports = {
    entry: './src/index.js', //入口文件
    output: {
        filename: 'bundle.[hash].js', // 默認(rèn)為main.js  [hash]是為了避免js緩存
        path: path.resolve(__dirname,'./dist') // path為絕對(duì)路徑杭攻,用node path模塊轉(zhuǎn)化
    },
    mode: 'development', // 開(kāi)發(fā)模式, 生產(chǎn)模式 'production' 會(huì)壓縮代碼
    module: { // 加載 css less
        rules: [
            {
                test: /\.css$/, // js 中 require css
                use: ['style-loader','css-loader']
            },
            { 
                test: /\.less$/, 
                // 注意順序
                use: ['style-loader','css-loader','less-loader'] 
            },
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                  loader: 'babel-loader',
                  options: {
                    presets: ['@babel/preset-env'],
                    plugins:[ // es6 內(nèi)置函數(shù)轉(zhuǎn)換
                        '@babel/plugin-transform-runtime'
                    ]
                  }
                }
            },
            {
                test: /\.(png|jpe?g|gif|m4a)$/, // 加載js img 對(duì)象祟敛、css 中的圖片、音頻等資源
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            //圖片大小小于等于limit值兆解,則會(huì)以base64形式加載馆铁,不會(huì)發(fā)請(qǐng)求,大于這個(gè)值則用file-loader加載
                            limit: 200*1024
                        }
                    }
                ]
            },
            {
                test: /\.html$/, // 加載 img 標(biāo)簽中的圖片
                use: [
                  {
                    loader: 'html-withimg-loader',
                    options: {}
                  }
                ]
            }
        ]
    },
    plugins:[ // 存放插件
        new HtmlWebpackPlugin({
            template: './src/index.html', // 模板
            filename: 'index.html', // 默認(rèn)也是index.html
            minify: {
                removeAttributeQuotes: true, // 刪除標(biāo)簽屬性的雙引號(hào)
                collapseInlineTagWhitespace: true, // 刪除多余空格
            },
            hash: true, // 增加hash锅睛,避免緩存
        }),
        new CleanWebpackPlugin()
    ],
    devServer:{ // 開(kāi)發(fā)服務(wù)器配置
        port: 3000, // 端口號(hào)
        progress: true, // 進(jìn)度條
        contentBase: './static', // 服務(wù)默認(rèn)指向文件夾
        inline: true, // 設(shè)置為true叼架,當(dāng)源文件改變的時(shí)候會(huì)自動(dòng)刷新
        historyApiFallback: true, // 在開(kāi)發(fā)單頁(yè)應(yīng)用時(shí)非常有用畔裕,它依賴于HTML5 history API,如果設(shè)置為true乖订,所有的跳轉(zhuǎn)將指向index.html
        hot: true, // 允許熱加載
        open: true // 自動(dòng)打開(kāi)瀏覽器
    }
}

最后 package.json 長(zhǎng)這個(gè)樣子(變了的只有 scripts 部分扮饶,配置腳本):

{
  "name": "audio-player",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --config webpack.config.js",
    "dev": "webpack-dev-server"
  },
  "author": "sparket",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.6.0",
    "@babel/plugin-transform-runtime": "^7.6.0",
    "@babel/preset-env": "^7.6.0",
    "babel-loader": "^8.0.6",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.2.0",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.10.3",
    "less-loader": "^5.0.0",
    "style-loader": "^1.0.0",
    "webpack": "^4.40.2",
    "webpack-cli": "^3.3.9",
    "webpack-dev-server": "^3.8.1"
  },
  "dependencies": {
    "@babel/polyfill": "^7.6.0",
    "@babel/runtime": "^7.6.0",
    "file-loader": "^4.2.0",
    "html-withimg-loader": "^0.1.16",
    "url-loader": "^2.1.0"
  }
}

參考資料:
1.http://www.reibang.com/p/99675e491ee6
2.http://www.reibang.com/p/f06e901860e
3.http://www.reibang.com/p/bacc576979fe

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者乍构。
  • 序言:七十年代末甜无,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子哥遮,更是在濱河造成了極大的恐慌岂丘,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眠饮,死亡現(xiàn)場(chǎng)離奇詭異奥帘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)仪召,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)寨蹋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扔茅,你說(shuō)我怎么就攤上這事已旧。” “怎么了召娜?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵运褪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我玖瘸,道長(zhǎng)秸讹,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任雅倒,我火速辦了婚禮嗦枢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屯断。我一直安慰自己文虏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布殖演。 她就那樣靜靜地躺著氧秘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趴久。 梳的紋絲不亂的頭發(fā)上丸相,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音彼棍,去河邊找鬼灭忠。 笑死膳算,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的弛作。 我是一名探鬼主播涕蜂,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼映琳!你這毒婦竟也來(lái)了机隙?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤萨西,失蹤者是張志新(化名)和其女友劉穎有鹿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體谎脯,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡葱跋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了源梭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娱俺。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖咸产,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仲闽,我是刑警寧澤脑溢,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站赖欣,受9級(jí)特大地震影響屑彻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜顶吮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一社牲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悴了,春花似錦搏恤、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至搞莺,卻和暖如春息罗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背才沧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工迈喉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绍刮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓挨摸,卻偏偏與公主長(zhǎng)得像孩革,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子油坝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348