咱們用webpack作單頁面應用開發應該嘗試過不少次了,若是在同一個項目須要支持PC端和移動端,作成多頁面應用,開發時能根據請求的終端返回不一樣的內容,應該怎麼作呢?如下描述的是我嘗試的一種方案,而且以vue-cli 2.x
提供的模板爲例,訪問 Github 可查看本項目源碼。html
由於是PC端和移動端兩個模塊,因此咱們能夠在src
下拆分爲pc
和mobile
兩個目錄,分別放兩端的代碼,再有一個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
複製代碼
由於有PC端和移動端,全部開發環境下應該有兩個entry
,分別爲src/pc/main.js
和src/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.js
的plugins
裏面,咱們做如下配置: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.js
。vendor.js
通常是公共代碼,manifest.js
是與webpack
加載代碼有關的包。app.js
通常是你寫的業務代碼,要注意的是,你配置了多少個入口文件,就會生成多少個這樣的包,好比咱們如今有兩個入口文件,分別是app
和mobile
,那麼就會生成app.js
和mobile.js
。github
上面的配置了兩個HtmlWebpackPlugin
,分別表明PC端和移動端的模板,他們chunks
字段也代表了在他們生成的html裏分別注入app.js
和mobile.js
。web
接下來咱們想在開發時,想根據訪問的客戶端,決定加載的是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
函數,官方文檔介紹以下:
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
函數,在函數裏你能夠拿到req
,res
和proxy
的引用, 最後必須返回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~