成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Webpack構(gòu)建多頁應(yīng)用心得體會(huì)

Ethan815 / 2770人閱讀

摘要:構(gòu)建的基于的多頁應(yīng)用腳手架,本文聊聊本次項(xiàng)目中構(gòu)建多頁應(yīng)用的一些心得體會(huì)。倉(cāng)庫(kù)構(gòu)建的舊版多頁應(yīng)用構(gòu)建的多頁應(yīng)用。例如多頁應(yīng)用中每個(gè)的值對(duì)應(yīng)的文件。

Webpack構(gòu)建的基于zepto的多頁應(yīng)用腳手架,本文聊聊本次項(xiàng)目中Webpack構(gòu)建多頁應(yīng)用的一些心得體會(huì)。

1.前言

由于公司舊版的腳手架是基于Gulp構(gòu)建的zepto多頁應(yīng)用(有興趣可以看看web-mobile-cli),有著不少的痛點(diǎn)。例如:

    需要兼容低版本瀏覽器,只能采用promise,不能使用awaitgenerator等。(因?yàn)?b>babel-runtime需要模塊化);

    瀏覽器緩存不友好(只能全緩存而不是使用資源文件的后綴哈希值來達(dá)到局部緩存的效果);

    項(xiàng)目的結(jié)構(gòu)不友好(可以更好的結(jié)構(gòu)化);

    開發(fā)環(huán)境下的構(gòu)建速度(內(nèi)存);

    Gulp插件相對(duì)Webpack少且久遠(yuǎn),維護(hù)成本高等等。

這次升級(jí)有幾個(gè)地方需要注意和改進(jìn):

    項(xiàng)目舊代碼盡量做到無縫轉(zhuǎn)移;

    資源文件的緩存;

    組件式的組織目錄結(jié)構(gòu)。

Github倉(cāng)庫(kù):

    Gulp構(gòu)建的舊版多頁應(yīng)用web-mobile-cli;

    Webpack構(gòu)建的多頁應(yīng)用web-mobile-webpack-cli。

2.多頁

Webpack的多頁應(yīng)用通過多入口entry和多實(shí)例html-webpack-plugin配合來構(gòu)建,html-webpack-pluginchunk屬性傳入對(duì)應(yīng)entrykey就可以做到關(guān)聯(lián),例如:

module.exports = {
  entry: {
    pageOne: "./src/pageOne/index.js",
    pageTwo: "./src/pageTwo/index.js",
    pageThree: "./src/pageThree/index.js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: `pageOne.html`,
      template: `./src/pageOne.html`,
      chunks: ["pageOne"]
    }),
    new HtmlWebpackPlugin({
      filename: `pageTwo.html`,
      template: `./src/pageTwo.html`,
      chunks: ["pageTwo"]
    }),
    new HtmlWebpackPlugin({
      filename: `pageTwo.html`,
      template: `./src/pageTwo.html`,
      chunks: ["pageTwo"]
    })
  ]
}

那么問題來了,開發(fā)新的頁面每次都得添加豈不是很麻煩。這里推薦神器glob根據(jù)正則規(guī)則匹配。

const glob = require("glob")

module.exports = {
  entry: glob.sync("./src/js/*.js").reduce((pre, filepath) => {
    const tempList = filepath.split("src/")[1].split(/js//)
    const filename = `${tempList[0]}${tempList[1].replace(/.js/g, "")}`
    
    return Object.assign(pre, {[filename]: filepath})
  }, {}),
  plugins: [
    ...glob.sync("./src/html/*.ejs").map((filepath, i) => {
      const tempList = filepath.split("src/")[1].split(/html//)
      const fileName = tempList[1].split(".")[0].split(/[/|//||]/g).pop()
      const fileChunk = `${tempList[0]}${fileName}`
      
      return new HtmlWebpackPlugin({
        filename: `${fileChunk}.html`,
        template: filepath,
        chunks: [fileChunk]
      })
    })
  ]
}
3.模板

項(xiàng)目沒有直接使用html,而是使用了ejs作為模板,這里有至少兩個(gè)好處:

    把公共的代碼抽離出來;

    傳入公共的變量。

// header.ejs
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title><%= title %>title>
head>

// index.ejs

<html lang="en">
<% include ./header.ejs %>
<body>
  
body>
<script src="<%= publicPath %>lib/zepto.js">script>
html>

<% include ./header.ejs %>就是引用了header.ejs文件,<%= title %><%= publicPath %>是我在配置文件定義的兩個(gè)變量,publicPath是為了統(tǒng)一cdn緩存服務(wù)器的域名,非常有用。

4.墊片

項(xiàng)目中使用了zepto,所以需要墊片,所謂墊片就是shim 預(yù)置依賴,即全局依賴。

webpack compiler 能夠識(shí)別遵循 ES2015 模塊語法、CommonJS 或 AMD 規(guī)范編寫的模塊。然而,一些 third party(第三方庫(kù)) 可能會(huì)引用一些全局依賴(例如 jQuery 中的 $)。因此這些 library 也可能會(huì)創(chuàng)建一些需要導(dǎo)出的全局變量。這些 "broken modules(不符合規(guī)范的模塊)" 就是 shim(預(yù)置依賴) 發(fā)揮作用的地方。

墊片有兩種方式:

    傳統(tǒng)方式的墊片就是在html文件中,所有引用的js文件的最前面引用的文件(例如zepto);

    Webpack配置shim預(yù)置依賴。

最終我選擇了Webpack配置shim預(yù)置依賴這種方式,因?yàn)椋?/p>

    傳統(tǒng)的方式需要每個(gè)頁面都手動(dòng)引入(雖說搭配ejs可以抽離出來成為公共模塊,但還是需要每個(gè)頁面手動(dòng)引入公共模塊);

    傳統(tǒng)的方式需要多發(fā)一次請(qǐng)求去請(qǐng)求墊片;

    Webpack可以把所有第三方插件的代碼都拆分打包成為一個(gè)獨(dú)立的chunk,只需一個(gè)請(qǐng)求。

module.exports = {
  entry: {...},
  module: {
    rules: [
      {
        test: require.resolve("zepto"),
        use: "imports-loader");
      }
    ]
  },
  plugins: [
    new webpack.ProvidePlugin({$: "zepto"})
  ]
}
5.拆分

一般來講Webpack的配置entry中每個(gè)key就對(duì)應(yīng)輸出一個(gè)chunk,那么該項(xiàng)目中會(huì)提取這幾類chunk

    頁面入口(entry)對(duì)應(yīng)的chunk;

    common:多次引用的公共文件;

    vender:第三方依賴;

    manifestWebpack運(yùn)行時(shí)(runtime)代碼,它存儲(chǔ)著Webpack對(duì)modulechunk的信息。

module.exports = {
  entry: {...},
  module: {...},
  plugins: [],
  optimization: {
    runtimeChunk: {
      name: "manifest"
    },
    splitChunks: {
      cacheGroups: {
        vendors: {
          test: /[/]node_modules[/]/,
          chunks: "all",
          name: "vendors",
          filename: "js/vendors.[contenthash:8].js",
          priority: 2,
          reuseExistingChunk: true
        },
        common: {
          test: /.m");,
          chunks: "all",
          name: "common",
          filename: "js/common.[contenthash:8].js",
          minSize: 0,
          minChunks: 2,
          priority: 1,
          reuseExistingChunk: true
        }
      }
    }
  }
}

這里注意的有兩點(diǎn):

    優(yōu)先順序:第三方插件的prioritycommon代碼的priority大;

    提取common代碼:minChunks為引用次數(shù),我設(shè)置為引用2次即提取為公共代碼。minSize為最小字節(jié),設(shè)置為0。

6.緩存

緩存的目的是為了提高加載速度,Webpack在緩存方面已經(jīng)是老生常談的了,每個(gè)文件賦予唯一的hash值,只有更新過的文件,hash值才改變,以達(dá)到整體項(xiàng)目最少文件改動(dòng)。

6.1 hash值

Webpack中有三種hash值:

    hash:全部文件同一hash,一旦某個(gè)文件改變,全部文件的hash都將改變(同一hash不滿足需求);

    chunkhash:根據(jù)不同的入口文件(Entry)進(jìn)行依賴文件解析、構(gòu)建對(duì)應(yīng)的chunk,生成對(duì)應(yīng)的哈希值(問題是css作為模塊importJavaScript文件中的,它們的chunkhash是一致的,一旦改變js文件,即使importcss文件內(nèi)容沒有改變,其chunkhash值也會(huì)一同改變,不滿足需求);

    contexthash:只有模塊的內(nèi)容變了,那么hash值才改變(采用)。

module.exports = {
  entry: {
    pageOne: "./src/pageOne/index.js",
    pageTwo: "./src/pageTwo/index.js",
    pageThree: "./src/pageThree/index.js"
  },
  output: {
    path: "src",
    chunkFilename: "j[name].[contenthash:8].js",
    filename: "[name].[contenthash:8].js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: `pageOne.html`,
      template: `./src/pageOne.html`,
      chunks: ["pageOne"]
    }),
    new HtmlWebpackPlugin({
      filename: `pageTwo.html`,
      template: `./src/pageTwo.html`,
      chunks: ["pageTwo"]
    }),
    new HtmlWebpackPlugin({
      filename: `pageTwo.html`,
      template: `./src/pageTwo.html`,
      chunks: ["pageTwo"]
    })
  ]
}
6.2 module id

僅僅使用contexthash還不足夠,每當(dāng)import的資源文件順序改變時(shí),chunk依然會(huì)改變,目的沒有達(dá)成。要解決這個(gè)問題首先要理解modulechunk分別是什么,簡(jiǎn)單理解:

    module:一個(gè)import對(duì)應(yīng)一個(gè)module(例如:import zepto from "zepto"中的zepto就是一個(gè)module);

    chunk:根據(jù)配置文件打包出來的包,就是chunk。(例如多頁應(yīng)用中每個(gè)entrykey值對(duì)應(yīng)的文件)。

因?yàn)?b>Webpack內(nèi)部維護(hù)了一個(gè)自增的id,依照順序賦予給每個(gè)module,每當(dāng)新增或者刪減導(dǎo)致module的順序改變時(shí),受影響的chunkhash值也會(huì)改變。解決辦法就是使用唯一的hash值替代自增的id。

module.exports = {
  entry: {...},
  module: {...},
  plugins: [],
  optimization: {
    moduleIds: "hashed"
  }
}
7.優(yōu)化

優(yōu)化的目的是提高執(zhí)行和打包的速度。

7.1 查找路徑

告訴Webpack解析模塊時(shí)應(yīng)該搜索的目錄,縮小編譯范圍,減少不必要的編譯工作。

const {resolve} = require("path")

module.exports = {
  entry: {...},
  module: {...},
  plugins: [],
  optimization: {...},
  resolve: {
    alias: {
      "@": resolve(__dirname, "../src"),
    },
    modules: [
      resolve("src"),
      resolve("node_modules"),
    ]
  }
}
7.2 指定目錄

指定loaderinclude目錄,作用是縮小編譯范圍。

const {resolve} = require("path")

module.exports = {
  entry: {...},
  module: {
    rules: [
      {
        test: /.css$/,
        include: [
          resolve("src"),
        ],
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  plugins: [],
  optimization: {...},
  resolve: {...}
}
7.3 babel緩存目錄

babel-loader開始緩存目錄cacheDirectory

const {resolve} = require("path")

module.exports = {
  entry: {...},
  module: {
    rules: [
      {
        test: /.m");,
        exclude: /(node_modules|bower_components)/,
        include: [
          resolve("src"),
        ],
        use: {
          loader: "babel-loader",
          options: {
            cacheDirectory: true,
            presets: ["@babel/preset-env"],
            plugins: ["@babel/plugin-transform-runtime"]
          }
        }
      }
    ]
  },
  plugins: [],
  optimization: {...},
  resolve: {...}
}
7.4 插件TerserJSPlugin

TerserJSPlugin插件的作用是壓縮JavaScript,優(yōu)化的地方是開啟緩存目錄和開啟多線程。

const {resolve} = require("path")

module.exports = {
  entry: {...},
  module: {...},
  plugins: [],
  optimization: {
    minimizer: [
      new TerserJSPlugin({
        parallel: true,
        cache: true,
      })
    ]
  },
  resolve: {...}
}
8.總結(jié)

通過這次學(xué)習(xí)Webpack到升級(jí)腳手架,對(duì)前端工程化有了進(jìn)一步的了解,也感受到了Webpack4帶來的開箱即用,挺方便的。

參考文章:
Webpack官方文檔
【實(shí)戰(zhàn)】webpack4 + ejs + express 帶你擼一個(gè)多頁應(yīng)用項(xiàng)目架構(gòu)
基于 webpack 的持久化緩存方案

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/6847.html

相關(guān)文章

  • 使用webpack構(gòu)建多頁應(yīng)用

    摘要:然而在某些特殊的應(yīng)用場(chǎng)景之中,則需要使用到傳統(tǒng)的多頁應(yīng)用。在使用進(jìn)行項(xiàng)目工程化構(gòu)建時(shí),也需要對(duì)應(yīng)到調(diào)整。配置入口設(shè)置多頁應(yīng)用的打包會(huì)對(duì)應(yīng)多個(gè)入口文件,以及多個(gè)模版文件。方法一使用的文件系統(tǒng)。組合如下完整可查看多頁應(yīng)用 背景 隨著react, vue, angular 三大前端框架在前端領(lǐng)域地位的穩(wěn)固,SPA應(yīng)用正在被應(yīng)用到越來越多的項(xiàng)目之中。然而在某些特殊的應(yīng)用場(chǎng)景之中,則需要使用到傳...

    IamDLY 評(píng)論0 收藏0
  • webpack多頁應(yīng)用架構(gòu)系列(十三):構(gòu)建一個(gè)簡(jiǎn)單的模板布局系統(tǒng)

    摘要:原文地址如果您對(duì)本系列文章感興趣,歡迎關(guān)注訂閱這里前言上文多頁應(yīng)用架構(gòu)系列十二利用生成普通網(wǎng)頁頁面模板我們基本上已經(jīng)搞清楚如何利用來生成普通網(wǎng)頁頁面模板,本文將以我的腳手架項(xiàng)目介紹如何在這基礎(chǔ)上搭建一套簡(jiǎn)單的模板布局系統(tǒng)。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000007...

    yedf 評(píng)論0 收藏0
  • webpack多頁應(yīng)用架構(gòu)系列(十五):論前端如何在后端渲染開發(fā)模式下夾縫生存

    摘要:回到純靜態(tài)頁面開發(fā)階段,讓頁面不需要后端渲染也能跑起來。改造開始本文著重介紹如何將靜態(tài)頁面改造成后端渲染需要的模板??偨Y(jié)在后端渲染的項(xiàng)目里使用多頁應(yīng)用架構(gòu)是絕對(duì)可行的,可不要給老頑固們嚇唬得又回到傳統(tǒng)前端架構(gòu)了。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/119000000820338...

    dinfer 評(píng)論0 收藏0
  • webpack多頁應(yīng)用架構(gòu)系列(十五):論前端如何在后端渲染開發(fā)模式下夾縫生存

    摘要:回到純靜態(tài)頁面開發(fā)階段,讓頁面不需要后端渲染也能跑起來。改造開始本文著重介紹如何將靜態(tài)頁面改造成后端渲染需要的模板??偨Y(jié)在后端渲染的項(xiàng)目里使用多頁應(yīng)用架構(gòu)是絕對(duì)可行的,可不要給老頑固們嚇唬得又回到傳統(tǒng)前端架構(gòu)了。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/119000000820338...

    dingda 評(píng)論0 收藏0
  • webpack多頁應(yīng)用架構(gòu)系列(一):一步一步解決架構(gòu)痛點(diǎn)

    摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址如果您對(duì)本系列文章感興趣,歡迎關(guān)注訂閱這里這系列文章講什么本系列文章主要介紹如何用這一當(dāng)前流行的構(gòu)建工具來設(shè)計(jì)一個(gè)多頁應(yīng)用的架構(gòu)。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000006843916如果您對(duì)本系列文章...

    Lowky 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<