webpack5搭建vue3教程(使用webpack搭建vue项目的步骤)
webpack5已经出来有一阵了,可是vue-cli要等到5.0版本才引入webpack5,主要担心的是nodejs的polyfills问题,
在vue-cli 5.0稳定之前,先自己搭建一遍,一些惯例尽量和vue-cli保持一致,求同存异.
教程不面向新手,你需要了解一些基本的webpack知识,比如loader,plugins,resolve
1. 初始化
新建一个目录,在该目录下执行命令
npm init 复制代码
会提示你一些选项,除了入口文件默认是index.js,我们这里和vue-cli保持一直输入main.js,剩下的直接回车就好. 会在目录下生成一个package.json文件
2.搭建webpack环境
npm i webpack webpack-merge webpack-dev-serve webpack-cli -D 复制代码
webpack是必装的,这个就不用介绍了
webpack-merge 这个是用来合并webpack配置文件的,比如一般项目有三个webpack配置文件,一个基础的 打包图片 样式啥的,一个生产环境的,一个开发环境的.开发环境就需要把基础配置文件合并进来再export
webpack-dev-serve 提供一个本地serve服务器,webpack5自带了一个serve但是传言日志不好,暂时还是dev serve webpack-cli webpack-cli 可以让你在命令行中调用webpack
3.创建目录和文件
创建红框里的目录和文件,其中index.html为了一致性直接用的vue-cli的index.html.把对ico文件的link那一行删掉
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <!-- built files will be auto injected --> </body> </html> 复制代码
当然,你也可以自己定义一个更简单的,比如这样
<!DOCTYPE html> <html lang=""> <body> <div id="app"></div> </body> </html> 复制代码
4.基本配置
我们先做一个最简单的配置,看看webpack能不能跑起来
webpack.common.js配置
const path = require('path') module.exports = env =>{ return { entry:'./src/main.js',//入口文件 stats: 'errors-only',//仅错误时显示logo output:{ filename: 'assets/js/[name].code.js', chunkFilename: 'assets/js/[name].bundle.js',//动态导入 分离bundle 比如lodashjs配合注释import(/* webpackChunkName: "lodash" */ 'lodash') 会打包成lodash.bundle.js path: path.resolve(__dirname, '../dist'), } } } 复制代码
webpack.prod.js配置
//const webpack = require('webpack'); const { merge } = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = env =>{ let pro_config = { mode:'production', // devtool:'source-map',//开启将会生成map文件 } return merge(common(env),pro_config) //合并配置 } 复制代码
main.js
console.log('this is mainjs') 复制代码
package.json
"scripts": { "build": "webpack --config build/webpack.prod.js" }, 复制代码
都是很基础的配置哈,大概说下逻辑.
当我们在命令行输入npm run build的时候,会执行webpack.prod.js文件,
在prod配置文件里,借助merge插件,会把webpack.common.js里的配置也执行起来.
在common文件里,入口是main.js,打包出口是dist目录 这时候我们执行run build 应该会看到新增加了一个目录,如图所示
5.根据业务需求配置插件
我们的目标是搭建一个类似vue-cli的脚手架,所以我们需要如下插件
vue-loader
loader 用于对模块的源代码进行转换,vue-loader当然就是对vue代码进行转换,让浏览器能够识别.
vue-loader除了在rules里配置外,还要在plugins配置下,是为了把其他定义的规则应用到vue文件里.
npm install vue@next -S npm install vue-loader@next @vue/compiler-sfc 复制代码
webpack.common.js文件:
const path = require('path') const { VueLoaderPlugin } = require('vue-loader') module.exports = env =>{ return { entry:'./src/main.js',//入口文件 output:{ filename: 'assets/js/[name].code.js', chunkFilename: 'assets/js/[name].bundle.js',//动态导入 分离bundle 比如lodashjs配合注释import(/* webpackChunkName: "lodash" */ 'lodash') 会打包成lodash.bundle.js path: path.resolve(__dirname, '../dist'), }, plugins:[ new VueLoaderPlugin() ], module:{ rules:[ { test:/\.vue$/, loader:'vue-loader' }, // 它会应用到普通的 `.js` 文件以及 `.vue` 文件中的 `<script>` 块 ] } } } 复制代码
HtmlWebpackPlugin
HtmlWebpackPlugin可以让打包后的JS自动引入html文件中
npm i -D html-webpack-plugin 复制代码
这个插件也属于生产和开发环境都用到的,所以在webpack.common.js文件里配置
const path = require('path') const { VueLoaderPlugin } = require('vue-loader') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = env =>{ return { entry:'./src/main.js',//入口文件 output:{ filename: 'assets/js/[name].code.js', chunkFilename: 'assets/js/[name].bundle.js',//动态导入 分离bundle 比如lodashjs配合注释import(/* webpackChunkName: "lodash" */ 'lodash') 会打包成lodash.bundle.js path: path.resolve(__dirname, '../dist'), }, plugins:[ new VueLoaderPlugin(), new HtmlWebpackPlugin({ template: path.join(__dirname, '../public/index.html'), filename: 'index.html',//输出的文件名 }), ], module:{ rules:[ { test:/\.vue$/, loader:'vue-loader' }, // 它会应用到普通的 `.js` 文件以及 `.vue` 文件中的 `<script>` 块 ] } } } 复制代码
bable-loader
这个就不多介绍了,能让你现在就用ES6 7 8的语法,官方教程
npm install -D babel-loader @babel/core @babel/preset-env webpack 复制代码
在webpack.common.js的rules里添加一条
module: { rules: [ { test: /\.vue$/, loader: "vue-loader", }, // 它会应用到普通的 `.js` 文件以及 `.vue` 文件中的 `<script>` 块 { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"], }, }, }, ], }, 复制代码
resolve
resolve主要是配置如会解析模块.常用的有两个extensions和alias,一个配置后缀名,可以不带后缀.一个配置引入别名,不用逐层引入
在webpack.common.js文件里配置
resolve:{ //配置模块如会解析 extensions:['.vue','.js','.json'],//引入这些文件 可以不带后缀 按顺序解析 alias:{ '@':join('../src'), //@方式引入资源 } }, 复制代码
资源模块
资源模块比如png svg jpg等图片或者txt等,webpack5之前都是用file-loader或者url-loader来处理.
webpack5现在会自动处理,不用再手动配置.小于8kb的资源视为inline资源处理,否则视为resource处理.
比如如果我们想规定小于6kb的图片才内联inline处理,否则就resource 引入.
webpack.common.js里
{ test: /\.(png|svg|jpg|gif)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 6 * 1024,//小于6kb的图片内联处理 } } } 复制代码
5.开发环境配置
上面主要是webpack.common.js基础配置,下面我们根据开发环境定制需要的配置.
friendly-errors-webpack-plugin
执行npm run serve成功之后,可以在控制台输出信息
const { merge } = require("webpack-merge"); const common = require("./webpack.common.js"); const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin"); const ip = require("ip"); let port = "8082"; module.exports = (env) => { let dev_config = { devtool: 'inline-source-map',//开启source map mode: "development", plugins: [ //运行成功,输出信息 new FriendlyErrorsPlugin({ compilationSuccessInfo: { messages: [ `You application is running here http://${ip.address()}:${port} \r\nYou can also open local address http://localhost:${port}`, ], clearConsole: true, }, }), ], }; return merge(common(env), dev_config); }; 复制代码
devserve
在devserve里我们可以指定端口啊,是否支持https,是否打卡浏览器窗口 在plugins下面增加一个同级的配置即可.
devServer: { host: "0.0.0.0", port: port, open:"http://localhost:" + port,//打开指定窗口 proxy: { "/api": { target: "http://www.xxx.com:8080/api", secure: true, // 如果是https接口,需要配置这个参数 changeOrigin: true, pathRewrite: { "^/finchinaAPP": "" }, }, }, }, 复制代码
cache
cache缓存生成的webpack模块和chunk,主要能提示构建速度.只在开发模式能用,默认是memory既缓存到内存中.
如果想自定义缓存策略,需要把cache的type值由memory改成filesystem.
比如修改默认缓存目录
const path = require('path'); module.exports = { //... cache: { type: 'filesystem', cacheDirectory: path.resolve(__dirname, '.temp_cache'), }, }; 复制代码
css处理
因为生产环境的CSS需要压缩,这里还是分别配置好了.
先安装style-loader 把CSS插入到DOM中.
npm install --save-dev style-loader 复制代码
再安装css-loader 对 @import
和 url()
进行处理,就像 js 解析 import/require()
一样.
npm install --save-dev css-loader 复制代码
最后在module的rules里增加一条规则
{ //解析器的执行顺序是从下往上(先css-loader再style-loader) test: /\.css$/i, use: [ "style-loader", { loader: "css-loader", options: { esModule: false, modules: { auto: false, //modules 开关,移动端多页面模式关闭class hash命名 localIdentName: "[local]_[hash:base64:8]", // 自定义生成的类名 }, }, }, ], }, 复制代码
sass-css处理
一般项目都会用到css处理器,所以光处理css是不够的,假如项目用的是sass-css,这么解决.
安装node-sass sass-loader
npm i node-sass -D npm install sass-loader sass webpack --save-dev 复制代码
在rulues里新增一个规则
{ test: /.s[ac]ss$/i, use: [ // 将 JS 字符串生成为 style 节点 'style-loader', // 将 CSS 转化成 CommonJS 模块 'css-loader', // 将 Sass 编译成 CSS 'sass-loader', ], }, 复制代码
less-css处理
如果用的是less-css 需要安装一个less-loader
npm install less less-loader --save-dev 复制代码
然后在rules里配置下
{ test: /\.less$/i, use: [ // compiles Less to CSS "style-loader", "css-loader", "less-loader", ], }, 复制代码
到此,我们的开发环境就配置完了.
6.生产环境配置
webpack5相对于4自动化增强了,比如会自动清除输出目录下的历史文件,自动压缩JS等 css-loader sass-loader less-loader上面已经介绍过了就不多介绍了.
提取css
借助MiniCssExtractPlugin插件
npm install --save-dev mini-css-extract-plugin 复制代码
然后在plugins和css loader配置
plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }), //提取CSS new MiniCssExtractPlugin({ filename:`assets/css/[name].style.css`, chunkFilename:`assets/css/[name].css` }), ], module: { rules: [ { //解析器的执行顺序是从下往上(先css-loader再style-loader) test: /\.css$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { esModule: false, modules:{ auto:false,//modules 开关,移动端多页面模式关闭class hash命名 localIdentName: '[local]_[hash:base64:8]',// 自定义生成的类名 } } }, ] }, { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ] }, { test: /\.less$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader' ] }, ] }, 复制代码
压缩css
webpack4使用的是OptimizeCSSAssetsPlugin,到了webpack5官方推荐使用CssMinimizerWebpackPlugin
npm install css-minimizer-webpack-plugin --save-dev 复制代码
然后在module同级新增一个配置
optimization: { minimizer: [ // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释 // `...`, new CssMinimizerPlugin(), ], } 复制代码
其实我们生产环境可以直接配置minimize: true,也行.
代码分离Optimization
Optimization,webpack5默认的构建目标是web,如果是别的比如node项目或者electorn项目,需要增加一个target属性
比如构建node环境
module.exports = { target: 'node', }; 复制代码
对于webpack的optimization,一般只关注optimization.splitChunks
splitChunks默认给我们配置了一套拆分规则
- 新的 chunk 可以被共享,或者模块来自于 `node_modules` 文件夹 - 新的 chunk 体积大于 20kb(在进行 min+gz 之前的体积) - 当按需加载 chunks 时,并行请求的最大数量小于或等于 30 - 当加载初始化页面时,并发请求的最大数量小于或等于 30 optimization: { splitChunks: { chunks: 'async', minSize: 20000, minRemainingSize: 0, minChunks: 1, maxAsyncRequests: 30, maxInitialRequests: 30, enforceSizeThreshold: 50000, cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, } 复制代码
我们也可以根据实际项目情况,做些调整,比如默认20kb开始分割代码,改成30KB分割代码等
splitChunks: { minChunks: 2, //模块至少使用次数 cacheGroups: { vendor: { name: 'vendor', test: /[\\/]node_modules[\\/]/, chunks: 'all', priority: 2, //2>0 nodulesmodules里的模块将优先打包进vendor }, commons: { name: "commons", //async异步代码分割 initial同步代码分割 all同步异步分割都开启 chunks: "all", minSize: 30000, //字节 引入的文件大于30kb才进行分割 priority: 0, //优先级,先打包到哪个组里面,值越大,优先级越高 } } } 复制代码
打包体积分析
打包后的代码,有时候文件比较大,需要分析下情况,这时候需要安装分析插件webpack-bundle-analyzer
npm install --save-dev webpack-bundle-analyzer 复制代码
然后配置只有监听到输入分析命令后才启动,不然每次打包都要启动
然后在package.json配置启动命令
"scripts": { "serve": "webpack-dev-server --hot --config build/webpack.dev.js", "dev": "webpack-dev-server --open --progress --config build/webpack.dev.js", "build": "webpack --config build/webpack.prod.js", "distanalyzer": "webpack --env.analyzer=true --config build/webpack.prod.js" }, 复制代码
至此,大功搞定.
7.跑起来试一下
安装vue-router
npm install vue-router@4 复制代码
简单写两个页面,成功!
作者:折叠幸福
链接:https://juejin.cn/post/7034810358795599880