热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

使用webpack搭建vue项目及注意事项

这篇文章主要介绍了使用webpack搭建vue项目的方法,本文以开发环境为例,通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

有一句话叫“前人栽树后人乘凉”,还有一句话叫“如果说我看得比别人更远些,那是因为我站在巨人的肩膀上”。前一句是国人的俗语,后一句是那个发现了“万有引力”定律的牛顿说的。为什么要引用这两句呢?是因为我刚开始用vue的时候,使用的是vue-cli来搭建vue项目,快速又好用;我刚开始用react的时候,使用的是create-react-app来搭建react项目,方便又省事。使用这些已有的脚手架来搭建项目,无可厚非,对于新手来说,也确实能快速构建,不做置评。

既然已经有了这些现成的脚手架了,为什么我们还热衷于自己来配置webpack来搭建构建项目呢?因为我们只有了解并学会了配置webpack,我们才能更好地在打包构建项目时将webpack的性能发挥到极致,才能根据自身项目的实际需求,配置有利于项目开发的各种工具、插件,提高我们的开发效率。比如我们在打包项目时,可以分析哪些地方降低了webpack的打包速度,别人打包速度需要花去十多秒、二十多秒,而你能将打包的速度提升至几秒,这就是你的优势。当然,涉及到webpack的运行原理以及开发自己的loader或plugin就可以自行去学习了哈,本文只带你配置一个webpack来搭建一个vue项目。

wepack作为一个“模块打包机”其实是依赖了庞大的插件体系,插件体系是webpack的核心,可以说,webpack的生态就是建立在众多插件之上的,而开发环境和生产打包环境依赖的插件还是有所不同的,先以开发环境为例

webpack.config.js:

const path = require('path');
const Webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');

const resolve = (dir) => {
 return path.join(__dirname, '..', dir)
}

const assetsPath = (_path) => {
 return path.join('static', _path)
}

const isEnvProduction = process.env.NODE_ENV == "production", port = 3003;

module.exports = {
 mode: 'development',
 devtool: 'source-map',
 entry: resolve('src'),
 output: {
  path: resolve('dist'),
  filename: isEnvProduction ? assetsPath('js/[name]-[hash].js') : '[name]-[hash].js',
  chunkFilename: isEnvProduction ? assetsPath('js/[name]-[chunkhash:5].min.js') : '[name]-[chunkhash:5].min.js',
  publicPath: '/',
 },
 resolve: {
  extensions: ['*', '.js', '.vue'], //webpack2.x extensions[0]不能为空 resolve属性中的extensions数组中用于配置程序可以自行补全哪些文件后缀
  alias: {
   '@': resolve('src'),
   // 'vue$': 'vue/dist/vue.esm.js'
  },
 },
 //提取公共代码
 optimization: {
  splitChunks: {
   cacheGroups: {
    commons: {
     test: /[\\/]node_modules[\\/]/, //表示默认拆分node_modules中的模块
     name: "vendor", //提取出来的文件命名
     chunks: "all",  //提取所有文件的公共部分
     minChunks: 2,   //表示提取公共部分最少的文件数 模块被引用>=2次,拆分至vendors公共模块
     minSize: 0,   //表示提取公共部分最小的大小 模块超过0k自动被抽离成公共模块
    },
   }
  }
 },
 module: {
  rules: [
   {
    test: /\.vue$/,
    use: ['vue-loader'],
    exclude: /node_modules/,
   },
   {
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: /node_modules/,
    query: {
     "presets": ["@babel/env"],
     "plugins":
      ["@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-runtime"],
    }
   },
   {
    test: /\.(sa|sc|c)ss$/,
    use: [
     MiniCssExtractPlugin.loader,
     'css-loader',
     'postcss-loader',
     'sass-loader',
    ],
   },
   {
    test: /\.(eot?.+|svg?.+|ttf?.+|otf?.+|woff?.+|woff2?.+)$/,
    use: 'file-loader?name=' + (isEnvProduction ? assetsPath('fonts/[name].[hash:8].[ext]') : 'fonts/[name].[hash:8].[ext]')
   },
   {
    test: /\.(jpg|jpeg|png|gif|ico|svg)$/,
    loader: 'url-loader',
    options: {
     limit: 10000,
     name: isEnvProduction ? assetsPath('images/[name].[hash:8].[ext]') : 'images/[name].[hash:8].[ext]',
    }
   },
  ],
 },
 plugins: [
  new ProgressBarPlugin(),
  new VueLoaderPlugin(),
  //ProvidePlugin是webpack的内置模块,使用ProvidePlugin加载的模块在使用时将不再需要import和require进行引入
  new Webpack.ProvidePlugin({
   _: 'lodash',
  }),
  new HtmlWebpackPlugin({
   template: './src/index.html', //文件路径及名称
   filename: 'index.html',   //输出后的文件名称
  }),
  new MiniCssExtractPlugin({
   filename: isEnvProduction ? assetsPath("css/[name]-[hash].css") : "css/[name]-[hash].css",
   chunkFilename: isEnvProduction ? assetsPath("css/[name]-[hash].css") : "css/[name]-[hash].css", //默认就是取的以id或name为开头的css,所以可以加这行配置代码,也可以不加
  }),
 ],
 devServer: {
  port,
  host: '0.0.0.0',
  open: `http://localhost:${port}`,
  stats: {
   hash: false,
   builtAt: false,
   version: false,
   modules: false,
   children: false, ////解决类似Entrypoint undefined = index.html和Entrypoint mini-css-extract-plugin = *的警告
   entrypoints: false,
   colors: {
    green: '\u001b[32m',
    yellow: '\u001b[32m',
   }
  },
  proxy: {
   '/': {
    target: '',
    changeOrigin: true
   }
  },
  inline: true,
  compress: false,
  disableHostCheck: true,
  historyApiFallback: true,
 },
}

关于配置中用到的一些插件的api就不一一展开详解了,唯一需要说明的一点是,配置中所用到的插件的版本基本都是最新的,而使用postcss-loader时,需要在项目的根目录新建一个postcss.config.js文件:

module.exports = { 
 plugins: { 
 'autoprefixer': {browsers: 'last 5 version'} 
 } 
}

以上是开发环境的webpack配置,下边是打包生产环境的配置webpack.product.config.js:

const path = require('path');
const cOnfig= require('./webpack.config');
const merge = require('webpack-merge');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //压缩单独的css文件
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin'); //资源清单
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); //监控打包文件所花费的时间,方便具体的性能优化
const smp = new SpeedMeasurePlugin();
const PurifyCSSPlugin = require("purifycss-webpack"); //css tree-shaking 依赖插件glob-all和purify-css
const glob = require("glob-all");

module.exports = smp.wrap(merge(config, {
 mode: 'production',
 stats: config.devServer.stats,
 devtool: false,
 //当我们想在项目中require一些其他的类库或者API,而又不想让这些类库的源码被构建到运行时文件中,这在实际开发中很有必要。此时我们就可以通过配置externals参数来解决这个问题
 externals: {
 'vue': 'Vue',
 'vuex': 'Vuex',
 'moment': 'moment',
 'vue-router': 'VueRouter',
 'element-ui': 'ELEMENT',
 'ant-design-vue': 'antd', //使用externals html里需手动引入一下js,特别注意:还需额外引入moment.js,并放在antd之前,否则会报错
 'lodash': '_',
 },
 optimization: {
 minimizer: [
  new UglifyJsPlugin({
  parallel: true, //使用多线程并行运行来提高构建速度,默认并发运行数量:os.cpus().length - 1
  uglifyOptions: {
   compress: {
   inline: false,
   drop_console: true, //是否屏蔽掉控制台输出
   },
  }
  }),
  new OptimizeCSSAssetsPlugin() //压缩css
 ]
 },
 plugins: [
 new ManifestPlugin(),
 new CleanWebpackPlugin(),
 new PurifyCSSPlugin({
  paths: glob.sync([
  // 要做CSS Tree Shaking的路径文件
  path.resolve(__dirname, "../src/*.vue")
  ])
 }),
 new HtmlWebpackPlugin({
  template: './src/index.prod.html', //打包时需要的文件路径和名称
  filename: 'index.html',    //打包输出后的文件名称
  minify: { //压缩html
  removeComments: true, //删除注释
  collapseWhitespace: true //删除空格
  }
 }),
 ],
}));

打包的配置中有几点需要注意:

1、配置中有一个speed-measure-webpack-plugin的插件,可以监控打包文件所花费的时间,方便具体的性能优化;

2、配置中加入了webpack-manifest-plugin生成资源清单的插件,这个插件所生成的资源清单对服务端渲染SSR非常有用,服务端可以根据当前的manifest,引入css和js文件;

3、配置中引入了purifycss-webpack和glob-all两个插件并依赖一个purify-css插件用来对css的tree-shaking。shake有摇动、抖动之意,言外之意就是通过抖动将项目中没有使用却定义了的js方法给删除,降低打包后项目的体积,很形象哈。自webpack2开始,webpack就自带了js的tree-shaking,却没有css的tree-shaking,所以我们就借助了插件来实现tree-shaking。

4、为了提高打包的速度以及降低打包后的项目体积,我们可以将项目中用到框架采用CDN的方式引入,从而将这部分框架排除在打包之外,而new HtmlWebpackPlugin配置项中的template的路径引用的index.prod.html文件就是采用CDN的方式引入的第三方的框架,区分了开发环境中的index.html。提升构建速度也可以通过DllPlugin和DLLReferencePlugin插件来实现,具体配置可参考:https://www.jb51.net/article/162789.htm

vue的项目目录:

react项目的webpack配置跟vue项目的webpack配置大同小异,这里不再多说,最后奉上package.json:

{
 "name": "webpackvue",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
 "test": "echo \"Error: no test specified\" && exit 1",
 "dev": "cross-env BABEL_ENV=development webpack-dev-server --config config/webpack.config.js",
 "build": "cross-env NODE_ENV=production webpack --config config/webpack.product.config.js"
 },
 "author": "",
 "license": "ISC",
 "devDependencies": {
 "@babel/core": "^7.4.4",
 "@babel/plugin-syntax-dynamic-import": "^7.2.0",
 "@babel/plugin-transform-runtime": "^7.4.4",
 "@babel/preset-env": "^7.4.4",
 "@babel/runtime": "^7.4.4",
 "autoprefixer": "^9.5.1",
 "babel-loader": "^8.0.6",
 "babel-plugin-import": "^1.11.2",
 "clean-webpack-plugin": "^2.0.2",
 "cross-env": "^5.2.0",
 "css-loader": "^2.1.1",
 "file-loader": "^3.0.1",
 "glob-all": "^3.1.0",
 "html-webpack-plugin": "^3.2.0",
 "lodash": "^4.17.11",
 "mini-css-extract-plugin": "^0.6.0",
 "node-sass": "^4.12.0",
 "optimize-css-assets-webpack-plugin": "^5.0.1",
 "postcss-loader": "^3.0.0",
 "progress-bar-webpack-plugin": "^1.12.1",
 "purify-css": "^1.2.5",
 "purifycss-webpack": "^0.7.0",
 "sass-loader": "^7.1.0",
 "speed-measure-webpack-plugin": "^1.3.1",
 "style-loader": "^0.23.1",
 "uglifyjs-webpack-plugin": "^2.1.3",
 "url-loader": "^1.1.2",
 "vue-loader": "^15.7.0",
 "vue-template-compiler": "^2.6.10",
 "webpack": "^4.31.0",
 "webpack-cli": "^3.3.2",
 "webpack-dev-server": "^3.3.1",
 "webpack-manifest-plugin": "^2.0.4",
 "webpack-merge": "^4.2.1"
 },
 "dependencies": {
 "ant-design-vue": "^1.3.9",
 "element-ui": "^2.8.2",
 "moment": "^2.24.0",
 "vue": "^2.6.10",
 "vue-router": "^3.0.6",
 "vuex": "^3.1.1"
 }
}

总结

以上所述是小编给大家介绍的使用webpack搭建vue项目及注意事项,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!


推荐阅读
  • 理解文档对象模型(DOM)
    本文介绍了文档对象模型(DOM)的基本概念,包括其作为HTML文档的节点树结构,以及如何通过JavaScript操作DOM来实现网页的动态交互。 ... [详细]
  • Java与JSON互转:实现JSON到Java对象及Java对象到JSON的转换
    本文详细介绍了如何在Java中实现JSON数据与Java对象之间的相互转换,包括代码示例和常见问题解决方法。 ... [详细]
  • Python数据类型6 字典
    字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包 ... [详细]
  • 微信小程序中实现位置获取的全面指南
    本文详细介绍了如何在微信小程序中实现地理位置的获取,包括通过微信官方API和腾讯地图API两种方式。文中不仅涵盖了必要的准备工作,如申请开发者密钥、下载并配置SDK等,还提供了处理用户授权及位置信息获取的具体代码示例。 ... [详细]
  • 本文探讨了Web开发与游戏开发之间的主要区别,旨在帮助开发者更好地理解两种开发领域的特性和需求。文章基于作者的实际经验和网络资料整理而成。 ... [详细]
  • 本文探讨了浏览器的同源策略限制及其对 AJAX 请求的影响,并详细介绍了如何在 Spring Boot 应用中优雅地处理跨域请求,特别是当请求包含自定义 Headers 时的解决方案。 ... [详细]
  • AngularJS在IE7中的兼容性解决方案
    本文探讨了在较旧版本的Internet Explorer(如IE7)中使用AngularJS时遇到的问题及解决方法,包括HTML标签的正确书写方式以及如何添加对JSON的支持。 ... [详细]
  • 本题要求计算给定两个正整数a和b时,2的-a次方与2的-b次方之和,并将结果以最简分数形式表示。输入包括多组测试数据,每组数据包含两个在2到20范围内的整数。 ... [详细]
  • 本文深入探讨 PHPCMS 平台中的字符串截取函数 str_cut 的使用方法,该函数常用于控制输出的标题或内容摘要长度,有效避免因过长的文本导致的页面布局问题。通过本文,读者将掌握如何灵活运用此函数,包括处理 HTML 标签等高级技巧。 ... [详细]
  • 探讨HTML中的DIV样式难题
    本文深入分析了HTML中常见的DIV样式问题,并提供了有效的解决策略。适合所有对Web前端开发感兴趣的读者。 ... [详细]
  • 本文探讨了为何需要进行详尽的需求分析,以及在软件开发过程中常见的需求类型。同时,介绍了几种有效的方法来确保能够准确地捕捉到用户的实际需求。 ... [详细]
  • JavaWeb技术架构解析
    本文探讨了JavaWeb开发中客户端与服务器端的交互模式,重点分析了B/S(浏览器/服务器)和C/S(客户端/服务器)两种架构的特点及应用场景。 ... [详细]
  • Vue 3.0 翻牌数字组件使用指南
    本文详细介绍了如何在 Vue 3.0 中使用翻牌数字组件,包括其基本设置和高级配置,旨在帮助开发者快速掌握并应用这一动态视觉效果。 ... [详细]
  • 深入理解Python编程
    本文探讨了作者在学习Python过程中遇到的挑战和转折点,以及如何通过找到合适的资源和方法来提升编程技能。对于初学者来说,这不仅是一个学习的过程,也是一个自我发现和调整学习策略的过程。 ... [详细]
  • 本文介绍了如何使用JavaScript和jQuery实现页面元素随着滚动条的移动而相应变化位置的功能,提供了一段简洁的代码示例。 ... [详细]
author-avatar
lmaster
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有