之前一直用的脚手架,这次自己搭建webpack前端项目,花费了不少心思,于是做个总结。
1.用法
项目结构如下:
project |- bulid <!-- 这个目录是自动生成的--> |- public |- css |- js |- page1.html <!-- 插件生成的html文件--> |- page2.html <!-- 插件生成的html文件--> ... |- public/ <!-- 存放字体、图片、网页模板等静态资源--> |- src <!-- 源码文件夹--> |- components/ |- css/ |- js/ |- page1.js <!-- 每个页面唯一的VUE实例,需绑定到#app--> |- page2.js <!-- 每个页面唯一的VUE实例,需绑定到#app--> ... |- package.json |- package-lock.json |- README.md
public文件夹存放一些静态文件,src文件夹存放源码。每个页面通过一个入口文件(page1.js,page2.js,..)生成vue实例,挂载到插件生成的html文件的#app元素上。
安装依赖
$ npm install
进入开发模式
$ npm run start
浏览器会打开 http://localhost:3000 ,这时页面一片空白,显示 cannot get几个字。不要慌,在url后面加上 /page1.html ,回车,便可看见我们的页面。 这是因为我把开发服务器的主页设置为 index.html ,而本例中页面为 page1.html,page2.html,因此会显示一片空白。
开发完成了,构建生产版本:
$ npm run build
这会产生一个build/文件夹,里面的文件都经过优化,服务器响应的资源,就是来自于这个文件夹。
2.介绍
2.1 webpack基础配置
我们的开发分为生产环境和开发环境,因此需要有2份webpack的配置文件(可能你会想用env环境变量,然后用3目运算符根据env的值返回不同值。然而这种方法在webpack导出模块的属性中无效,我试过~~~)。这里我们拆分成3个文件,其中 webpack.common.js 是常规的配置,在两种环境下都会用到, webpack.dev.js 和 webpack.prod.js 则是在2种环境下的特有配置。这里用到 webpack-merge 这个包,将公共配置和特有配置进行合成。
webpack.common.js const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const devMode = process.env.NODE_ENV !=='production'; // 需要被打包入口文件数组 // 数组元素类型 {string|object} // string:将以默认规则生成bundle // object{filename|title|template} 生成的bundle.html的文件名|title标签内容|路径 /public 下的模板文件(需指定文件后缀) const entryList = [ 'page1', 'page2', ]; /** * @param {array} entryList * @param {object} option:可选 要手动配置的内容 */ const createEntry = (list = [], option = {}) => { const obj = {}; list.forEach((item) => { const name = item.filename "htmlcode">webpack.dev.js const webpack = require('webpack'); const path = require('path'); const merge = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common, { mode: 'development', devtool: 'inline-source-map', output: { filename: '[name].js', chunkFilename: '[name].js', }, module: { rules: [ { test: /\.(css|less)$/, use: [ 'vue-style-loader', 'css-loader', 'postcss-loader', 'less-loader' ], }, ], }, resolve: { alias: { vue: 'vue/dist/vue.js' } }, });vue分为开发版本和生产版本,最后一行是根据路径指定使用哪个版本。
webpack.prod.js
const webpack = require('webpack'); const merge = require('webpack-merge'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const common = require('./webpack.common.js'); module.exports = merge(common, { mode: 'production', output: { filename: '[name].[contenthash].js', chunkFilename: '[name].[contenthash].js', }, resolve: { alias: { vue: 'vue/dist/vue.min.js' } }, module: { rules: [ { test: /\.(css|less)$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader' ], }, ], },在production环境下,我们使用了哈希值便于缓存,以后往生产环境下添加其他资源都会如此。
2.2 解决文件输出目录
我们期待的build文件夹具有如下结构:
build
|- css/
|- js/
|- page1.html
|- page2.html
...即文件按照类型放在一起,html文件直接放在该目录下,可是我们上面的配置的输出结果是混合在一起的。由于name属性既可以是文件名,也可以是 /dir/a 之类带有路径的文件名,我们根据这个特点做出一些修改。
直接对output的输出路径更改
比如改为 build/js ,其他资源利用相对路径比如 ../page1.html 进行修改。我一开始就这样做的,但最终会导致开发服务器无法响应文件的变化,因为他只能针对输出目录下的文件进行监听,该目录之上的文件变化无能为力。
修改入口名称
这也是我们的最终解决方案。将原来的文件名 page1 修改为 /js/page1 ,最终输出的js文件便都会放在js文件夹里。在生产环境下我们通过 MiniCssExtractPlugin 这个插件提取js文件中的css,这是该插件的配置:
new MiniCssExtractPlugin({ filename:'[name].[contenthash].css' })这里的name就是当初入口的名字,受到入口名称更改的影响,上面最终会变成 js/page1.131de8553ft82.css ,并且该占位符[name]只在编译时有效,这意味着无法用函数对该值进行处理。因此不能使用[name]占位符达到想要的目的,干脆只用[id]。
new MiniCssExtractPlugin({ filename:'/css/[id].[contenthash].css' })3.代码分割
在webpack4中使用optimization.splitChunks进行分割.
//webpack.common.js const path = require('path'); module.exports = { // ... 省略其他内容 optimization:{ runtimeChunk:{ name:'./js/runtime' }, splitChunks:{ // 避免过度分割,设置尺寸不小于30kb //cacheGroups会继承这个值 minSize:30000, cacheGroups:{ //vue相关框架 main:{ test: /[\\/]node_modules[\\/]vue[\\/]/, name: './js/main', chunks:'all' }, //除Vue之外其他框架 vendors:{ test:/[\\/]node_modules[\\/]"color: #ff0000">4.树抖动在package.json里加入
"sideEffects":["*.css","*.less","*.sass"]
该数组之外的文件将会受到树抖动的影响——未使用的代码将会从export导出对象中剔除。这将大大减少无用代码。如果树抖动对某些文件具有副作用,就把这些文件名放进数组以跳过此操作。css文件(包括.less,.sass)都必须放进来,否则会出现样式丢失。
5. 插件的使用
5.1 clean-webpack-plugin
每次打包后都会生成新的文件,这可能会导致无用的旧文件堆积,对于这些无用文件自己一个个删太麻烦,这个插件会在每次打包前自动清理。实际中,我们不想在开发环境下清理掉build命令生成的文件,因此只在生产环境使用了这个插件。
5.2 html-Webpack-plugin
我们的源码目录中并没有html文件,打包后的多个html文件,就是我们用这个插件生成的。
//webpack.common.js // ...省略上面已经出现过的内容 //每个html需要一个插件实例 //批量生成html文件 const createPluginInstance = (list = []) => ( list.map((item) => { return new HtmlWebpackPlugin({ filename: item.filename "htmlcode">//webpack.prod.js //...省略其他内容 plugins:[ new CleanWebpackPlugin('build'), // 提取css new MiniCssExtractPlugin({ filename:'./css/[id].[contenthash].css' }), //优化缓存 new webpack.HashedModuleIdsPlugin() ]5.4 optimize-css-assets-webpack-plugin (production)
用于精简打包后的css代码,设置在配置optimization的minimizer属性中,这将会覆盖webpack默认设置,因此也要同时设置js的精简工具(这里我们用uglifyplugin插件):
optimization: { minimizer:[ new UglifyJsPlugin({ cache: true, parallel: true }), new OptimizeCSSAssetsPlugin() ] }6.开发服务器、热模块替换 (development)
webpack.dev.js中增加如下内容即可:
//...省略其他内容 devServer:{ index:'index.html', hot:true, contentBase:path.resolve(__dirname,'./build'), port:3000, noInfo:true }, plugins:[ new webpack.HotModuleReplacementPlugin() ]使用开发服务器可以在我们修改了源文件后自动刷新,因为是将数据放在内存中,因此不会影响硬盘中build文件夹。热模块替换还需要在源文件做相应修改。我们也为动态导入语法进行了相应配置。
7.其他
public用于存放静态资源,打包后也会在build/下创建一个同名文件夹,里面存放的是public会被使用到的资源。如果在.css文件里引用了public里的资源,如图片,添加url的时候要使用绝对路径:
<!-- src/css/page1.css --> .bg-img { background-image:url(/public/images/1.jpg) }这样通过 http/https 打开的时候就能正常使用,如果是以文件形式打开(比如打包后双击page1.html),会发现浏览器显示无法找到资源。通过导入图片作为变量引用( import name from path ),既可使用绝对路径,也可使用相对路径。
总结
以上所述是小编给大家介绍的webpack4打包vue前端多页面项目,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
华山资源网 Design By www.eoogi.com
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]
- 周深《反深代词》[先听版][320K/MP3][72.71MB]
- 李佳薇.2024-会发光的【黑籁音乐】【FLAC分轨】
- 后弦.2012-很有爱【天浩盛世】【WAV+CUE】
- 林俊吉.2012-将你惜命命【美华】【WAV+CUE】
- 晓雅《分享》DTS-WAV
- 黑鸭子2008-飞歌[首版][WAV+CUE]
- 黄乙玲1989-水泼落地难收回[日本天龙版][WAV+CUE]
- 周深《反深代词》[先听版][FLAC/分轨][310.97MB]
- 姜育恒1984《什么时候·串起又散落》台湾复刻版[WAV+CUE][1G]
- 那英《如今》引进版[WAV+CUE][1G]
- 蔡幸娟.1991-真的让我爱你吗【飞碟】【WAV+CUE】
- 群星.2024-好团圆电视剧原声带【TME】【FLAC分轨】