webpack使用體驗(yàn)

node知識(shí)

path.resolve

path.resolve(from[...pathname], to)將參數(shù)to位置的字符解析到一個(gè)絕對(duì)路徑里。
__dirname 當(dāng)前文件目錄絕對(duì)路徑
__filename 當(dāng)前文件全路徑
demo示例:(當(dāng)前目錄: D:\www\programs\react-prod\config)

// 相對(duì)路徑根據(jù)當(dāng)前位置絕對(duì)路徑解析
// ../匹配上一層
// ./ 或者 沒(méi)有./匹配當(dāng)前路徑
// D:\www\programs\react-prod\config\dist
path.resolve('./dist')
// D:\www\programs\react-prod\dist
path.resolve('../dist')
// D:\www\programs\react-prod\config\www\dist
path.resolve('www/demo', '../dist')
// D:\dist絕對(duì)路徑直接返回
path.resolve('/dist')

// 如果只傳遞一個(gè)參數(shù),那么相對(duì)路徑將基于當(dāng)前命令的執(zhí)行路徑
輸出

console.log(path.resolve('./dist'))
console.log(path.resolve(__dirname, './dist'))

當(dāng)在D:\www\programs\react-prod路徑下執(zhí)行時(shí),分別返回

D:\www\programs\react-prod\dist
D:\www\programs\react-prod\script\dist

當(dāng)在D:\www\programs\react-prod\script路徑下執(zhí)行時(shí),分別返回

D:\\www\\programs\\react-prod\\script\\dist
D:\\www\\programs\\react-prod\\script\\dist

所以為了表現(xiàn)一致,path里面解析絕對(duì)路徑,需要加上__dirname


webpack知識(shí)

context
配置基礎(chǔ)目錄,使config中的相對(duì)路徑基于這個(gè)目錄,這樣,不管webpack配置文件放在哪里,我們?cè)谖募?nèi)部引用外部文件時(shí),都可以根據(jù)一個(gè)相同的基礎(chǔ)目錄解析文件,只需修改config.context一個(gè)地方就可以了。

entry入口

用法:

  1. 單入口: entry: string|Array<string>,傳入數(shù)組會(huì)將數(shù)組中的文件作為統(tǒng)一一個(gè)入口一起打包成一個(gè)文件
  2. 多入口: 用法:entry: {[entryChunkName: string]: string|Array<string>}根據(jù)入口打包成多個(gè)js文件

output輸出

在 webpack 中配置 output 屬性的最低要求是,將它的值設(shè)置為一個(gè)對(duì)象,包括以下兩點(diǎn):

  1. filename 用于輸出文件的文件名。
  2. 目標(biāo)輸出目錄 path 的絕對(duì)路徑。

常用loaders

1.css-loader

css加載器 css-loader, style-loader
css-loader 解釋(interpret) @import 和 url() ,會(huì) import/require() 后再解析(resolve)它們
style-loader用來(lái)將解析出來(lái)的css內(nèi)容添加到頁(yè)面的style標(biāo)簽里面。但是一般情況下我們都會(huì)將css樣式與js文件分離,這樣可以有效減小代碼體積。2.66kb -> 816bytes+27bytes
css-loader+style-loader一般需要結(jié)合兩個(gè)plugin一起使用,分別用于將css分離和壓縮

// 用于提取css的plugin
const ExtractTextPlugin = require('extract-text-webpack-plugin')
// 用于壓縮css的plugin
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
...
// module.rules[num]
{
    test: /\.css$/,
    // 它會(huì)將所有的入口chunk(entry chunks)中引用的 *.css,
    // 移動(dòng)到獨(dú)立分離的 CSS 文件
    // css bundle 與 js bundle 并行加載,加快頁(yè)面初始化
    use: ExtractTextPlugin.extract({
      fallback: 'style-loader',
      use: 'css-loader'
    })
    // style-loader用來(lái)將css-loader解析(import,url()等)出來(lái)的css
    // 插入到頁(yè)面的<style>標(biāo)簽里面,沒(méi)有則無(wú)法正常引用
    // 使用etp時(shí)則作為降級(jí)處理
    // use: ['style-loader', 'css-loader']
}
...
plugins: [
    // name為入口里面的名字,將抽離的css合并成文件
    // 對(duì)每個(gè)入口chunk都生成一個(gè)對(duì)應(yīng)的文件
    // 所以當(dāng)你配置多個(gè)入口 chunk 的時(shí)候
    // 必須使用[name],[id]或[contenthash]
    new ExtractTextPlugin('css/[name].css'),
    // 壓縮css
    new OptimizeCssAssetsPlugin({
      // 匹配需要壓縮的文件
      assetNameRegExp: /\.css$/g,
      // 壓縮使用的插件
      cssProcessor: require('cssnano'),
      cssProcessorOptions: { discardComments: {removeAll: true } },
      canPrint: true
    })
]

2.file-loader
file-loader用來(lái)解析資源文件,可以自定義解析生成的文件名,路徑等等,用來(lái)處理css中的background-image以及js中import一個(gè)img等引用資源的情景。
file-loader存在一個(gè)很大的坑就是,我們往往需要使用相對(duì)路徑去解析打包文件中設(shè)計(jì)的圖片資源,并且將打包生成的css,images分別放在不同的目錄,比如我們規(guī)定解析生成的img的路徑名稱為:assets/images/demo.png,那么不管是在css還是在js的img引用中,引用路徑都會(huì)是'assets/images/demo.png',在html中,由于本身目錄結(jié)構(gòu)與asset平級(jí),可以順利引用,但是在css中就不行了,引用路徑就會(huì)變成dist/assets/css/assets/image/demo.png。emmm,自然是不行的。在網(wǎng)上找了一大圈,全是什么亂七八糟的,要么牛頭不對(duì)馬嘴,要么自?shī)首詷?lè),要么強(qiáng)行裝逼...真是無(wú)力吐槽。真正有用的信息總是被垃圾信息掩蓋,不過(guò)費(fèi)了九牛二虎之力,還是找到了行之有效的解決辦法,傳送門。這里利用了extract-text-webpack-plugin的publicPath屬性,這個(gè)屬性的作用是,重新設(shè)置loader解析出來(lái)的文件的publicPath。作用就是,比如你在css里面本來(lái)的引用路徑是'assets/images/demo.png',通過(guò)設(shè)置publicPath,引用路徑就變成了'../../assets/images/demo.png'。根據(jù)本例的路徑,(返回到assets層,再返回到dist層)最終解析的路徑就是'dist/assets/images/demo.png'。ok,至此,import、url()的路徑都是正常的啦。網(wǎng)上有一種解決方案是使用絕對(duì)路徑,額,大胸弟,我覺(jué)得這個(gè)很不妥吧,你能保證你的目錄外面沒(méi)有嵌套個(gè)幾層?比如給咱的應(yīng)用套個(gè)apapa的殼?(emmmm.很偏激,歡迎指正) 可以結(jié)合圖片壓縮plugin,比如壓縮生成的雪碧圖。

{
    test: /\.(png|svg|jpe?g|gif)$/i,
    use: {
      loader: 'file-loader',
      options: {
        name: 'assets/images/[name].[ext]'
      }
    }
}

// css-loader做如下修改
{
    test: /\.css$/,
    // 它會(huì)將所有的入口 chunk(entry chunks)中引用的 *.css,
    // 移動(dòng)到獨(dú)立分離的 CSS 文件
    // css bundle 與 js bundle 并行加載
    use: ExtractTextPlugin.extract({
      fallback: 'style-loader',
      // 定義文件內(nèi)部引用的路徑
      // 原路徑加上../../(基于assets/images/)
      // 用來(lái)處理url文件引用
+     publicPath: '../../',
      use: 'css-loader'
    })
}

3.babel-loader
babel-loader的作用是在webpack里面使用babel。emmm....
用法如下

{
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    use: {
      // 依賴babel-loader,babel-core
      // 等價(jià)于
      // loader: 'babel-loader?presets=env&compact=false',
      loader: 'babel-loader',
      options: {
        // 將es6的語(yǔ)法轉(zhuǎn)換成es5
        presets: [
          ["env", {

            // 如果兼容性要求不高,可以添加target屬性
            // 減少polyfill的代碼量,并且直接使用es6新特性
            "targets": {
              "browsers": ["last 2 versions", "safari >= 7"]
            },
            // 交由 Webpack 來(lái)處理模塊化(決定使用import/require)
            // 通過(guò)其 TreeShaking 特性將有效減少打包出來(lái)的JS文件大小867bytes->817bytes
            "modules": false
          }]
        ],
        // babel-plugin-transform-runtime
        // babel-runtime
        // 避免模塊的重復(fù)引用,polyfills功能,修復(fù)es6高級(jí)語(yǔ)法不兼容問(wèn)題
        // 與babel-polyfill的區(qū)別在于runtime會(huì)按需加載,不會(huì)污染全局
        plugins: ['transform-runtime'],
        // 緩存編譯結(jié)果
        cacheDirectory: true,
        // 去掉多余的空行與換行符
        compact: true
      }
    }
}

4.ts-loader
使用ts開(kāi)發(fā)時(shí),需要使用ts-loader進(jìn)行type check,但是ts-loader在執(zhí)行檢測(cè)的過(guò)程中,是單線程執(zhí)行,這會(huì)造成編譯時(shí)間巨長(zhǎng)無(wú)比。在這里使用awesome-typescript-loader替代

{
    test: /\.tsx?$/,
    use: {
      loader: 'awesome-typescript-loader',
      options: {
        useBabel: true,
        babelOptions: {
          babelrc: false, /* Important line */
          presets: [
            ["env", { "targets": "last 2 versions, ie 11", "modules": false }]
          ],
          // polyfill
          plugins: ['transform-runtime'],
        },
        babelCore: "babel-core", // needed for Babel v7
        errorsAsWarnings: true, // 類型錯(cuò)誤warning,而不是error
      }
},

常用插件

1.HtmlWebpackPlugin
該插件將為你生成一個(gè)HTML5文件,其中包括使用script標(biāo)簽的body中的所有webpack包

new HtmlWebpackPlugin({
  // 定義html文件的title,如果指定模板則無(wú)效
  title: '我的生涯一片無(wú)悔,想起那天下午夕陽(yáng)下的奔跑,那是我逝去的青春',
  favicon: './assets/images/favicon.ico',
  template: './template/page.html',
  filename: 'index.html',
  // 只引入指定的入口文件生成的chunks,默認(rèn)引入所有
  chunks: ['bar'],
  // 將生成的文件插入html中的位置
  inject: 'body',
  // 給生成的js,css添加一個(gè)唯一的hash
  // assets/js/bar.js?b34fce8721458861ac22
  hash: true,
  cache: true
  
  // 使用插件,豐富template
  // 將生成的文件插入html中的位置
  // html-webpack-template結(jié)合使用時(shí)需要置為false
  // 個(gè)人覺(jué)得不好用,不夠直觀,不玩了
  // inject: false,
  // template: require('html-webpack-template'),
  // appMountId: 'app',
}),

2.clean-webpack-plugin
清除文件夾,比如清除之前生成的dist

// 清理dist,默認(rèn)基于__dirname,可以自己傳參配置,
// 如果目錄在root之外,則無(wú)法順利清除
// root需要包含被清除目錄
new CleanWebpackPlugin(['dist'], {root: path.resolve(__dirname, '../')}),

3.extract-text-webpack-plugin與optimize-css-assets-webpack-plugin
分離cs壓縮css

// 它會(huì)將所有的入口 chunk(entry chunks)中引用的 *.css,
// 移動(dòng)到獨(dú)立分離的 CSS 文件
// css bundle 與 js bundle 并行加載
test: /\.css$/,
use: ExtractTextPlugin.extract({
  fallback: 'style-loader',
  // 定義文件內(nèi)部引用的路徑
  // 原路徑加上../../(基于assets/images/)
  // 用來(lái)處理url文件引用路徑不正確問(wèn)題
  publicPath: '../../',
  use: 'css-loader'
})

// name為入口里面的名字,將抽離的css合并成文件
// 所以一個(gè)入口生成一個(gè)css文件,在HtmlWebpackPlugin中
// 將根據(jù)入口將對(duì)應(yīng)的css文件綁定到html
// 對(duì)每個(gè)入口chunk都生成一個(gè)對(duì)應(yīng)的文件
// 所以當(dāng)你配置多個(gè)入口 chunk 的時(shí)候
// 必須使用[name],[id]或[contenthash]
new ExtractTextPlugin('assets/css/[name].css'),

// 壓縮css
new OptimizeCssAssetsPlugin({
  assetNameRegExp: /\.css$/g,
  cssProcessor: require('cssnano'),
  cssProcessorOptions: { discardComments: { removeAll: true } },
  canPrint: true
})

4.new webpack.optimize.UglifyJsPlugin()
壓縮打包后的文件
使用插件替代uglifyjs-webpack-plugin

// 壓縮打包后的文件
new UglifyJSPlugin({
  // 生產(chǎn)環(huán)境使用source-map
  sourceMap: true
})

5.hard-source-webpack-plugin
緩存編譯結(jié)果,加速編譯,效果顯著

// 緩存編譯結(jié)果,縮短編譯時(shí)間
new HardSourceWebpackPlugin(),

概念

webpack打包的代碼分成三個(gè)部分,第一個(gè)是自己編寫(xiě)的代碼,第二部分為引入的第三方庫(kù)與依賴,第三個(gè)部分是webpack用來(lái)進(jìn)行模塊加載與邏輯解析(runtime)和模塊交互的部分(mainfest)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。 webpack介紹和使用 一、webpack介紹 1、由來(lái) ...
    it筱竹閱讀 11,457評(píng)論 0 21
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,940評(píng)論 25 709
  • 目錄第1章 webpack簡(jiǎn)介 11.1 webpack是什么? 11.2 官網(wǎng)地址 21.3 為什么使用 web...
    lemonzoey閱讀 1,822評(píng)論 0 1
  • 一開(kāi)始想用permutations那種全排列來(lái)計(jì)算,DFS寫(xiě)了好久發(fā)現(xiàn)人家n可以是9位數(shù),遞歸幾千萬(wàn)次這得什么計(jì)算...
    DrunkPian0閱讀 330評(píng)論 0 0
  • 【養(yǎng)身篇】中醫(yī)說(shuō)“恐傷腎”中醫(yī)認(rèn)為恐為腎之志長(zhǎng)期恐懼或突然意外驚恐皆能導(dǎo)致腎氣受損所謂恐傷腎,就是指的這個(gè)意思腎主...
    晨曦_邱月暉閱讀 1,516評(píng)論 0 0

友情鏈接更多精彩內(nèi)容