快速配置webpack多入口脚手架
背景
当我们基于vue开发单个项目时,我们会init一个vue-cli,但当我们想在其他项目里共用这套模板时,就需要重新init一个,或者clone过来,这非常不方便,而且当多人开发时,我们希望所有的开发代码都在一个git目录下,这时就有了对webpack进行配置的需求,当有些页面需要多入口时,我们又产生了对多入口配置的需求,这里提供一种配置方案,希望能帮助到有需要的人,废话不多说,我们开始吧!
先初始化一个项目
我们通过vue init webpack demo 生成的文件目录是这样的
修改项目入口
要改多入口,首先改造一下webpack.base.conf.js
中的context
和entry
。
context:基础目录,绝对路径,用于从配置中解析入口起点(entry point)和 loader。
entry:起点或是应用程序的起点入口。从这个起点开始,应用程序启动执行。
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
};
如果项目只有一个入口,那么直接在这里改entry就可以了,但一般我们都是多个项目在放一个目录里,所以要提取出来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
,用于设置当前启动项目,并将这个文件添加到.gitignore中,因为以后多人开发都是在本地修改项目地址。
'use strict'
module.exports = {
appName: 'mobile',
projectName: 'demo'
}
这里设计2个目录,appName是src下的一级目录,projectName是appName下的二级目录,目的在于方便拓展,比如公司的项目分为pc项目和mobile项目,开发时便于区分,如果你的项目比较少,那可以把appName写成一个固定字符串如:pages,每次切换项目只更改projectName就可以了。我们将所有项目放在src下,类似目录如下
├─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()) // 项目根目录 fs.realpathSync表示获取真实路径
const resolve = relativePath => path.resolve(rootPath, relativePath) // 自定义一个resolve函数,拼接出需要的路径地址
module.exports = {
rootPath, // 项目根目录
commonPath: resolve('common'), // 公共目录
projectPath: resolve(`src/${_config.appName}/${_config.projectName}`), // 子项目根目录
config: resolve('config'), // 项目配置
static: resolve('static') // 公共静态资源目录
}
新建common文件夹
我们在src同级新建一个common文件夹,用于存放静态资源及公共组件
-components
├─assets
├─components
└─xhr
assets里可以存放公共样式css,公共字体font,公共图片img,公共方法js等;components里存放提取出来的公共组件,xhr我放的是axio的封装,整个文件夹可以自定义修改,这里就不展开了,如果项目比较简单不需要,在paths.js里删去对应的部分即可。
再来看我们修改的entry,我们在config文件夹中的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
}
实际上就是对当前项目entry文件中的js文件进行遍历,如果是单个就是单入口,多个就是多入口。
创建2个项目
- assets 静态资源
- config.js 代理配置、打包地址等配置
- entry 入口文件夹
demo1是一个单入口项目,demo2是一个多入口项目,如果是多入口项目,需要在entry增加对应的js文件,如上图中的more.html和more.js,上面的getEntry其实找的就是index.js和more.js。
我们再看一下demo2中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/>'
})
引入对应的组件就好,再看下config.js
const host = 'http://xxx.com/api' // 测试地址
module.exports = {
dev: {
// proxy代理配置
proxyTable: {
'/api': {
target: host, // 源地址
changeOrigin: true, // 改变源
logLevel: 'debug',
ws: true,
pathRewrite: {
'^/api': '' // 路径重写
}
}
},
build: {
// build输出路径
// assetsRoot: path.resolve(process.cwd(), '')
}
// 是否启用postcss-pxtorem插件 https://github.com/cuth/postcss-pxtorem
// pxtorem: true
}
}
这里就是根据需要自行配置了,如果不需要完全可以不要这个文件,重要的还是entry的入口文件。
打包出口配置
入口改好了,我们再看出口,找到如下内容
// 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的作用是生成一个 HTML5 文件,CopyWebpackPlugin的作用是将单个文件或整个目录复制到构建目录。我们在utils.js中新建2个方法getHtmlWebpackPlugin和getCopyWebpackPlugin,对这两个方法进行替换,让他们支持多入口。改动后如下
// 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
// 改动
...utils.getHtmlWebpackPlugin(baseWebpackConfig),
// copy custom static assets
// 改动
...utils.getCopyWebpackPlugin()
]
// webpack.prod.conf.js
// 改动
...utils.getHtmlWebpackPlugin(baseWebpackConfig),
// 省略
// 改动
...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,对其做一些修改,让我们可以在项目里的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')) // 子项目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 || './',
// 省略
}
到这里,我们的多入口配置就基本完成了,注意修改过的配置文件里一些引用需要加上,检查下路径是否正确。
既然我们的目的就是打造多入口模板,那么以demo2为例,运行npm run dev 在如果服务是http://localhost:8080,多页面入口在浏览器访问时url就是http://localhost:8080/more.html。注意要带.html哦。
运行npm run build 我们会发现dist文件夹里有2个html,说明多入口打包成功
到此我们的项目模板就配置完成了。以后多人开发、多入口活动都可以在这个项目下进行开发了,此篇不涉及webpack优化,只提供一种配置思路。如果感觉文章写的不够清楚,或者想直接使用这个模板,我的git上有完整的脚手架
传送门,如果遇到问题或者好的建议,欢迎提出。
快速配置webpack多入口脚手架的更多相关文章
- 快速配置webpack+vue项目
第一步:初始化项目 1.npm init 2. package name: (webpack+vue) webpackvue version: (1.0.0) description: this is ...
- 快速配置webpack 4.x
区分开发模式和生产模式: npm run start——开发模式,启用devServer,文件的改动实时更新.刷新 npm run build——生产模式,打包文件到dist文件夹 // packag ...
- webpack快速入门——配置文件:入口和出口,多入口、多出口配置
1.在根目录新建一个webpack.config.js文件,然后开始配置: const path = require('path'); module.exports={ //入口文件的配置项 entr ...
- create-react-app脚手架中配置webpack的方法
概述 create-react-app脚手架中的react-scripts能够(1)帮我们自动下载需要的webpack依赖:(2)自己写了一个nodejs服务端脚本代码:(3)使用express的Ht ...
- Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务
Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具:Spr ...
- Webpack实战(三):作为前端你不得不懂的Webpack资源入口和出口的配置
关于Webpack前两篇跟大家分享的主要是Webpack的一些基本的配置,今天开始我们详细了解一下有关Webpack的各种配置,今天主要跟大家分享的是Webpack的资源入口和资源出口的配置. 如果想 ...
- 【前端】一步一步使用webpack+react+scss脚手架重构项目
前言 前几天做了一个项目:[node]记录项目的开始与完成——pipeline_kafka流式数据库管理项目:因为开发时间紧迫,浅略的使用了一下react,感觉这个ui库非常的符合我的口味,现在趁着有 ...
- webpack浅析---入口篇
webpack有四个核心概念: 入口(entry) 输出(output) loader 插件(plugins) webpack-merge将环境.构建目标.运行时合并 入口: 入口起点是指webpac ...
- 一步一步使用webpack+react+scss脚手架重构项目
前几天做了一个项目:[node]记录项目的开始与完成——pipeline_kafka流式数据库管理项目:因为开发时间紧迫,浅略的使用了一下react,感觉这个ui库非常的符合我的口味,现在趁着有空闲时 ...
随机推荐
- Web Api返回值
首先:注明,我还没这么强的功力啦!这是我看的网上的,因为怕博主删除就自己复制了一下 博主的网址是:http://www.cnblogs.com/landeanfen/p/5501487.html 使用 ...
- spring boot 2.0.3+spring cloud (Finchley)8、微服务监控Spring Boot Admin
参考:Spring Boot Admin 2.0 上手 Spring Boot Admin 用于管理和监控一个或多个Spring Boot程序,在 Spring Boot Actuator 的基础上提 ...
- Uva5211/POJ1873 The Fortified Forest 凸包
LINK 题意:给出点集,每个点有个价值v和长度l,问把其中几个点取掉,用这几个点的长度能把剩下的点围住,要求剩下的点价值和最大,拿掉的点最少且剩余长度最长. 思路:1999WF中的水题.考虑到其点的 ...
- 「七天自制PHP框架」应用:JSON生成器
刚刚开始学做一个WebAPP,数据查询的一般套路是通过一张PHP页面读取数据库,获得列表后“嵌写”在PHP页面中,虽然写法上丑陋至极,但也有“快糙猛”出效果的成就感,如图. 后来想想,不对啊,难道以后 ...
- JVM学习三:JVM之类加载器之连接分析
学习完类加载之加载篇后,让我们继续来看加载之连接,连接分为三个步骤:验证.准备和解析三步,我们将一一分析之. 连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去. 类加载完毕之后进入 ...
- DOM操作二三事
我突然想起了append(),但是我记不太清它是原生JS的还是jQuery封装的,貌似是JS的,咦?那它在jQuery里叫什么来着?哎呀!记不清了!确定append()是JS里的?不是jQuery里的 ...
- [php]referer应用--http防盗链技术
1.防盗链的理解 所谓防盗链是防止其他的网站引用自己网站的资源连接,比如图片.视频等等,但是并不会阻碍从自己网站上享受资源的用户,这就要求能够将其他网站的连接请求阻止 2.防盗链的原理 其实从自己网站 ...
- 【LibreOJ】#6257. 「CodePlus 2017 12 月赛」可做题2
[题意]数列满足an=an-1+an-2,n>=3.现在a1=i,a2=[l,r],要求满足ak%p=m的整数a2有多少个.10^18. [算法]数论(扩欧)+矩阵快速幂 [题解]定义fib(i ...
- (值类型引用类型)和null的关系
1.null null表示变量没有指向任何对象. 2.值类型 包括 bool.结构体.枚举.int.double.float等等 .在.NET中值类型都继承自ValueType. 3. 引 ...
- redis笔记之两种持久化备份方式(RDB & AOF)
Redis支持的两种持久化备份方式(RDB & AOF) redis支持两种持久化方式,一种是RDB,一种是AOF. RDB是根据指定的规则定时将内存中的数据备份到硬盘上,AOF是在每次执行命 ...