基於webpack的PC端和mobile端開發以及生產環境的搭建

咱們用webpack作單頁面應用開發應該嘗試過不少次了,若是在同一個項目須要支持PC端和移動端,作成多頁面應用,開發時能根據請求的終端返回不一樣的內容,應該怎麼作呢?如下描述的是我嘗試的一種方案,而且以vue-cli 2.x提供的模板爲例,訪問 Github 可查看本項目源碼。html

目錄架構

由於是PC端和移動端兩個模塊,因此咱們能夠在src下拆分爲pcmobile兩個目錄,分別放兩端的代碼,再有一個common目錄放置常量、數據層、api層等公共資源和可複用代碼:vue

├── build
│ ├── webpack.config.base.js
│ ├── webpack.config.dev.js
│ └── webpack.config.prod.js
├── src
│   ├──common
│   │   ├── assets
│   │   ├── constants
│   │   ├── store
│   │   │  └── index.js
│   │   |── api
│   │   │  └── index.js
│   ├── pc
│   │   |── pages
│   │   │  |── Home.vue
│   │   │  └── About.vue
│   │   |── App.vue
│   │   |── index.html
│   │   └── main.js
│   ├── mobile
│   │   │  |── Home.vue
│   │   │  └── About.vue
│   │   |── App.vue
│   │   |── index.html
│   │   └── main.js
複製代碼

webpack配置

由於有PC端和移動端,全部開發環境下應該有兩個entry,分別爲src/pc/main.jssrc/mobile/main.js,參考webpack文檔的多入口配置,因此咱們在webpack.config.base.js可作以下修改:react

entry: {
    app: './src/pc/main.js',
    mobile: './src/mobile/main.js',
  },
複製代碼

完成以上修改後,咱們分別對開發環境和打包環境做配置。webpack

開發環境配置

在這裏咱們要作的是,可讓webpack既能夠同時根據PC端和mobile端的模版生成對應的html並注入打包後的js文件,這個時候咱們要藉助HtmlWebpackPlugin這個插件幫咱們實現。因此,在webpack.config.dev.jsplugins裏面,咱們做如下配置:git

plugins: [

    // ....

    // PC端
    new HtmlWebpackPlugin({
      filename: 'index.html', // 最後生成的文件名
      template: 'src/pc/index.html', // 模版html
      chunks: ['manifest', 'vendor', 'app'], // 注入打包後的js文件
      inject: true,
    }),
    // 移動端
    new HtmlWebpackPlugin({
      filename: 'index.mobile.html',
      template:'src/mobile/index.html',
      chunks: ['manifest', 'vendor', 'mobile'],
      inject: true,
    }),


    // ....
  ],
複製代碼

上面的配置要特別說明下的是chunks字段。webpack通過打包後通常會生成vendor.js,manifest.js,app.jsvendor.js通常是公共代碼,manifest.js是與webpack加載代碼有關的包。app.js通常是你寫的業務代碼,要注意的是,你配置了多少個入口文件,就會生成多少個這樣的包,好比咱們如今有兩個入口文件,分別是appmobile,那麼就會生成app.jsmobile.jsgithub

上面的配置了兩個HtmlWebpackPlugin,分別表明PC端和移動端的模板,他們chunks字段也代表了在他們生成的html裏分別注入app.jsmobile.jsweb

接下來咱們想在開發時,想根據訪問的客戶端,決定加載的是PC端模版仍是mobile端模板。好比在chrome瀏覽器直接打開時,咱們就加載PC端模版index.html,若是咱們打開了 chrome devtools,切換到移動端調試工具,那麼刷新以後咱們加載移動端的模版index.mobile.html,這個時候咱們就能夠藉助webpack-dev-server工具了。chrome

咱們在webpack環境下開發,都會用到這個工具,不管是vue的腳手架vue-cli仍是react的腳手架create-react-app都自帶了這個工具。腳手架就是利用這個工具來啓動本地服務的,其實webpack-dev-server內部使用了一箇中間件叫作webpack-dev-middleware來啓動web服務。vue-cli

只要咱們在webpack中配置devServer這個屬性,就能使用了webpack-dev-server了。咱們做以下配置(若是是vue-cli建立的項目,則在config/index.js裏做相應配置):api

devServer: {
    proxy: {
      '/': {
        target: 'http://localhost:8080', // 你項目的本地服務地址
        bypass: function(req, res, proxyOptions) {
          const userAgent = req.headers['user-agent'];
          if (req.headers.accept.indexOf('html') !== -1) {
            // 根據訪問終端返回模板
            if (/mobile/i.test(userAgent) && !/iPad/i.test(userAgent)) {
              return '/index.mobile.html';
            }
            return '/index.html';
          }
        },
      },
    },
  }
複製代碼

這裏咱們代理了/的每一個請求,若是用戶的請求資源類型不是html,那麼就而後根據用戶的user-agent返回不一樣的模板。

這裏要說一下的是bypass函數,官方文檔介紹以下:

webpack.js.org/configurati…

Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a function.

In the function you get access to the request, response and proxy options. It must return either false or a path that will be served instead of continuing to proxy the request.

E.g. for a browser request, you want to serve a HTML page, but for an API request you want to proxy it.

這段文字的大意是,有時候對於瀏覽器的某些請求,你但願提供HTML頁面,你可設置bypass函數,在函數裏你能夠拿到reqresproxy的引用, 最後必須返回false或資源提供的路徑,使這個請求再也不繼續代理請求。

通過上面配置以後,咱們的開發就相對方便些了,只要咱們在chrome devtools切換環境並刷新,webpack就會自動返回對應的模板。

注意:若是直接訪問http://localhost:8080是沒法按照客戶端的user-agent返回任務東西的(不通過bypass函數),必須在後面加多一個路徑才行,好比http://localhost:8080/path,這個問題有待解決。

生產環境配置

生產環境要配置的很少,只要配置HtmlWebpackPlugin就能夠了

plugins: [

    // ....

    // PC端模版
    new HtmlWebpackPlugin({
      filename: path.resolve(__dirname, '../dist/index.html'),
      template: 'src/pc/index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true,
      },
      chunksSortMode: 'dependency',
      chunks: ['manifest', 'vendor', 'app'],
    }),
    // 移動端模版
    new HtmlWebpackPlugin({
      filename: path.resolve(__dirname, '../dist/mobile_index.html'),
      template: 'src/mobile/index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true,
      },
      chunksSortMode: 'dependency',
      chunks: ['manifest', 'vendor', 'mobile'],
    }),
    // ....
  ],
複製代碼

通過配置就會生成文件了,可是有一個問題是,vendor.js會包含PC端和移動端的代碼,可能有一些代碼其中由一方是用不上的,好比UI框架,個人解決辦法是在模版手動注入vue/react包和對應的UI框架,這種方法還有一個好處是減小vendor包的大小。。。

最後再貼一下項目 github 地址,歡迎star~

本文連接:www.zzfweb.cn/post/webpac…

相關文章
相關標籤/搜索