詳解如何快速配置webpack多入口腳手架

背景

網(wǎng)站建設(shè)、做網(wǎng)站的關(guān)注點(diǎn)不是能為您做些什么網(wǎng)站,而是怎么做網(wǎng)站,有沒(méi)有做好網(wǎng)站,給創(chuàng)新互聯(lián)公司一個(gè)展示的機(jī)會(huì)來(lái)證明自己,這并不會(huì)花費(fèi)您太多時(shí)間,或許會(huì)給您帶來(lái)新的靈感和驚喜。面向用戶友好,注重用戶體驗(yàn),一切以用戶為中心。

當(dāng)我們基于vue開(kāi)發(fā)單個(gè)項(xiàng)目時(shí),我們會(huì)init一個(gè)vue-cli,但當(dāng)我們想在其他項(xiàng)目里共用這套模板時(shí),就需要重新init一個(gè),或者clone過(guò)來(lái),這非常不方便,而且當(dāng)多人開(kāi)發(fā)時(shí),我們希望所有的開(kāi)發(fā)代碼都在一個(gè)git目錄下,這時(shí)就有了對(duì)webpack進(jìn)行配置的需求,當(dāng)有些頁(yè)面需要多入口時(shí),我們又產(chǎn)生了對(duì)多入口配置的需求,這里提供一種配置方案,希望能幫助到有需要的人,廢話不多說(shuō),我們開(kāi)始吧!

先初始化一個(gè)項(xiàng)目

我們通過(guò)vue init webpack demo 生成的文件目錄是這樣的

詳解如何快速配置webpack多入口腳手架

修改項(xiàng)目入口

要改多入口,首先改造一下 webpack.base.conf.js 中的 contextentry 。

context:基礎(chǔ)目錄,絕對(duì)路徑,用于從配置中解析入口起點(diǎn)(entry point)和 loader。

entry:起點(diǎn)或是應(yīng)用程序的起點(diǎn)入口。從這個(gè)起點(diǎn)開(kāi)始,應(yīng)用程序啟動(dòng)執(zhí)行。

module.exports = {
 context: path.resolve(__dirname, '../'),
 entry: {
  app: './src/main.js'
 },
};

如果項(xiàng)目只有一個(gè)入口,那么直接在這里改entry就可以了,但一般我們都是多個(gè)項(xiàng)目在放一個(gè)目錄里,所以要提取出來(lái)context和entry。

const paths = require('./paths')
const rootPath = paths.rootPath
module.exports = {
 context: rootPath
 entry: {
  app: utils.getEntry(),
 }, 
};

在config里新建 _config.js 和 paths.js

_config.js ,用于設(shè)置當(dāng)前啟動(dòng)項(xiàng)目,并將這個(gè)文件添加到.gitignore中,因?yàn)橐院蠖嗳碎_(kāi)發(fā)都是在本地修改項(xiàng)目地址。

'use strict'
 module.exports = {
 appName: 'mobile',
 projectName: 'demo'
}

這里設(shè)計(jì)2個(gè)目錄,appName是src下的一級(jí)目錄,projectName是appName下的二級(jí)目錄,目的在于方便拓展,比如公司的項(xiàng)目分為pc項(xiàng)目和mobile項(xiàng)目,開(kāi)發(fā)時(shí)便于區(qū)分,如果你的項(xiàng)目比較少,那可以把a(bǔ)ppName寫(xiě)成一個(gè)固定字符串如:pages,每次切換項(xiàng)目只更改projectName就可以了。我們將所有項(xiàng)目放在src下,類(lèi)似目錄如下

├─mobile
│ ├─demo
│ └─demo2
└─pc
  ├─demo
  └─demo2

paths.js ,用于配置一些全局需要用到的路徑

'use strict'
const path = require('path')
const fs = require('fs')
const _config = require('./_config')

const rootPath = fs.realpathSync(process.cwd()) // 項(xiàng)目根目錄 fs.realpathSync表示獲取真實(shí)路徑
const resolve = relativePath => path.resolve(rootPath, relativePath) // 自定義一個(gè)resolve函數(shù),拼接出需要的路徑地址
module.exports = {
 rootPath, // 項(xiàng)目根目錄
 commonPath: resolve('common'), // 公共目錄
 projectPath: resolve(`src/${_config.appName}/${_config.projectName}`), // 子項(xiàng)目根目錄
 config: resolve('config'), // 項(xiàng)目配置
 static: resolve('static') // 公共靜態(tài)資源目錄
}

新建common文件夾

我們?cè)趕rc同級(jí)新建一個(gè)common文件夾,用于存放靜態(tài)資源及公共組件

-components 
 ├─assets
 ├─components
 └─xhr

assets里可以存放公共樣式css,公共字體font,公共圖片img,公共方法js等;components里存放提取出來(lái)的公共組件,xhr我放的是axio的封裝,整個(gè)文件夾可以自定義修改,這里就不展開(kāi)了,如果項(xiàng)目比較簡(jiǎn)單不需要,在paths.js里刪去對(duì)應(yīng)的部分即可。

再來(lái)看我們修改的entry,我們?cè)赾onfig文件夾中的utils.js 新增了getEntry方法,并在entry處引用。

'use strict'
// 省略...
const paths = require('./paths')
const fs = require('fs')
// 省略...
exports.getEntry = () => {
 const entryPath = path.resolve(paths.projectPath, 'entry')
 const entryNames = fs
   .readdirSync(entryPath)
   .filter(n => /\.js$/g.test(n))
   .map(n => n.replace(/\.js$/g, ''))
 const entryMap = {}

 entryNames.forEach(
   name =>
   (entryMap[name] = [
     ...['babel-polyfill', path.resolve(entryPath, `${name}.js`)]
   ])
 )
 return entryMap
}

實(shí)際上就是對(duì)當(dāng)前項(xiàng)目entry文件中的js文件進(jìn)行遍歷,如果是單個(gè)就是單入口,多個(gè)就是多入口。

創(chuàng)建2個(gè)項(xiàng)目

詳解如何快速配置webpack多入口腳手架

  • assets 靜態(tài)資源
  • config.js 代理配置、打包地址等配置
  • entry 入口文件夾

demo1是一個(gè)單入口項(xiàng)目,demo2是一個(gè)多入口項(xiàng)目,如果是多入口項(xiàng)目,需要在entry增加對(duì)應(yīng)的js文件,如上圖中的more.html和more.js,上面的getEntry其實(shí)找的就是index.js和more.js。

我們?cè)倏匆幌耫emo2中entry中的index.js和more.js

// index.js
import Vue from 'vue'
import App from '../App'

new Vue({
 el: '#app',
 router,
 components: { App },
 template: '<App/>'
})
// more.js
import Vue from 'vue'
import App from '../More'

new Vue({
 el: '#more',
 components: { App },
 template: '<App/>'
})

引入對(duì)應(yīng)的組件就好,再看下config.js

const host = 'http://xxx.com/api' // 測(cè)試地址

module.exports = {
 dev: {
  // proxy代理配置
  proxyTable: {
   '/api': {
    target: host, // 源地址
    changeOrigin: true, // 改變?cè)?    logLevel: 'debug',
    ws: true,
    pathRewrite: {
     '^/api': '' // 路徑重寫(xiě)
    }
   }
  },
  build: {
   // build輸出路徑
   // assetsRoot: path.resolve(process.cwd(), '')
  }
  // 是否啟用postcss-pxtorem插件 https://github.com/cuth/postcss-pxtorem
  // pxtorem: true
 }
}

這里就是根據(jù)需要自行配置了,如果不需要完全可以不要這個(gè)文件,重要的還是entry的入口文件。

打包出口配置

入口改好了,我們?cè)倏闯隹冢业饺缦聝?nèi)容

// webpack.dev.conf.js
plugins: [
  new webpack.DefinePlugin({
   'process.env': require('../config/dev.env')
  }),
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
  new webpack.NoEmitOnErrorsPlugin(),
  // https://github.com/ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
   filename: 'index.html',
   template: 'index.html',
   inject: true
  }),
  // copy custom static assets
  new CopyWebpackPlugin([
   {
    from: path.resolve(__dirname, '../static'),
    to: config.dev.assetsSubDirectory,
    ignore: ['.*']
   }
  ])
 ]
// webpack.prod.conf.js
new HtmlWebpackPlugin({
   filename: config.build.index,
   template: 'index.html',
   inject: true,
   minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: true
    // more options:
    // https://github.com/kangax/html-minifier#options-quick-reference
   },
   // necessary to consistently work with multiple chunks via CommonsChunkPlugin
   chunksSortMode: 'dependency'
  }),
// 省略
// copy custom static assets
  new CopyWebpackPlugin([
   {
    from: path.resolve(__dirname, '../static'),
    to: config.build.assetsSubDirectory,
    ignore: ['.*']
   }
  ])

HtmlWebpackPlugin的作用是生成一個(gè) HTML5 文件,CopyWebpackPlugin的作用是將單個(gè)文件或整個(gè)目錄復(fù)制到構(gòu)建目錄。我們?cè)趗tils.js中新建2個(gè)方法getHtmlWebpackPlugin和getCopyWebpackPlugin,對(duì)這兩個(gè)方法進(jìn)行替換,讓他們支持多入口。改動(dòng)后如下

// webpack.dev.conf.js
 plugins: [
  new webpack.DefinePlugin({
   'process.env': require('./dev.env')
  }),
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
  new webpack.NoEmitOnErrorsPlugin(),
  // https://github.com/ampedandwired/html-webpack-plugin
  // 改動(dòng)
  ...utils.getHtmlWebpackPlugin(baseWebpackConfig),
  // copy custom static assets
  // 改動(dòng)
  ...utils.getCopyWebpackPlugin()
 ]
// webpack.prod.conf.js
  // 改動(dòng)
   ...utils.getHtmlWebpackPlugin(baseWebpackConfig),
  // 省略
  // 改動(dòng)
   ...utils.getCopyWebpackPlugin()
// utils.js
exports.getHtmlWebpackPlugin = baseWebpackConfig => {
 const HtmlWebpackPluginList = []
 const entryNames = Object.keys(baseWebpackConfig.entry)
 entryNames.forEach(name => {
   HtmlWebpackPluginList.push(
     new HtmlWebpackPlugin(
       Object.assign({
           filename: config.build.filename && process.env.NODE_ENV == 'production' ? config.build.filename : `${name}.html`,
           template: config.build.template && process.env.NODE_ENV == 'production' ? path.resolve(
             paths.projectPath, config.build.template) : path.resolve(
             paths.projectPath,
             `${name}.html`
           ),
           inject: true,
           excludeChunks: entryNames.filter(n => n !== name)
         },
         process.env.NODE_ENV === 'production' ? {
           minify: {
             removeComments: true,
             collapseWhitespace: true
               // removeAttributeQuotes: true
           },
           chunksSortMode: 'dependency'
         } : {}
       )
     )
   )
 })
 return HtmlWebpackPluginList
}

exports.getCopyWebpackPlugin = () => {
 const projectStaticPath = path.resolve(paths.projectPath, 'static')
 const assetsSubDirectory =
   process.env.NODE_ENV === 'production' ?
   config.build.assetsSubDirectory :
   config.dev.assetsSubDirectory
 const rootConfig = {
   from: paths.static,
   to: assetsSubDirectory,
   ignore: ['.*']
 }
 const projectConfig = {
   from: projectStaticPath,
   to: assetsSubDirectory,
   ignore: ['.*']
 }
 return [
   new CopyWebpackPlugin(
     fs.existsSync(projectStaticPath) ? [rootConfig, projectConfig] : [rootConfig]
   )
 ]
}

修改index.js

我們找到config里index.js,對(duì)其做一些修改,讓我們可以在項(xiàng)目里的config.js中配置代理,打包目錄,讓模板更靈活。

// config/index.js 改造前
 dev: {
  // Paths
  assetsSubDirectory: 'static',
  assetsPublicPath: '/',
  proxyTable: {},
  // Various Dev Server settings
  host: 'localhost', // can be overwritten by process.env.HOST 
 },
 build: {
  // Template for index.html
  index: path.resolve(__dirname, '../dist/index.html'),

  // Paths
  assetsRoot: path.resolve(__dirname, '../dist'),
  assetsSubDirectory: 'static',
  assetsPublicPath: '/',
  // 省略
 }
//config/index.js 改造后
const paths = require('./paths')
const resolve = relativePath => path.resolve(paths.projectPath, relativePath)
const _config = require(resolve('config.js')) // 子項(xiàng)目webpack配置
 dev: {
  // Paths
  assetsSubDirectory: 'static',
  assetsPublicPath: '/',
  proxyTable: _config.dev.proxyTable,
  // Various Dev Server settings
  host: '0.0.0.0', // can be overwritten by process.env.HOST 
 },
 build: {
  // Template for index.html
  index: path.resolve(__dirname, '../dist/index.html'),

  // Paths
  assetsRoot: _config.build.assetsRoot || path.resolve(__dirname, '../dist'),
  assetsSubDirectory: 'static',
  assetsPublicPath: _config.build.publichPath || './',
  // 省略
 }

到這里,我們的多入口配置就基本完成了,注意修改過(guò)的配置文件里一些引用需要加上,檢查下路徑是否正確。

既然我們的目的就是打造多入口模板,那么以demo2為例,運(yùn)行npm run dev 在如果服務(wù)是http://localhost:8080,多頁(yè)面入口在瀏覽器訪問(wèn)時(shí)url就是http://localhost:8080/more.html。注意要帶.html哦。

運(yùn)行npm run build 我們會(huì)發(fā)現(xiàn)dist文件夾里有2個(gè)html,說(shuō)明多入口打包成功

詳解如何快速配置webpack多入口腳手架

到此我們的項(xiàng)目模板就配置完成了。以后多人開(kāi)發(fā)、多入口活動(dòng)都可以在這個(gè)項(xiàng)目下進(jìn)行開(kāi)發(fā)了,此篇不涉及webpack優(yōu)化,只提供一種配置思路。如果感覺(jué)文章寫(xiě)的不夠清楚,或者想直接使用這個(gè)模板,我的git上有完整的腳手架

傳送門(mén) ,如果遇到問(wèn)題或者好的建議,歡迎提出。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

網(wǎng)頁(yè)題目:詳解如何快速配置webpack多入口腳手架
文章地址:http://bm7419.com/article30/igicso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、電子商務(wù)自適應(yīng)網(wǎng)站、網(wǎng)站設(shè)計(jì)公司手機(jī)網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)