webpack5搭建vue环境
0.前言
- 安装 webpack、webpack-cli 【开始我是全局安装进行测试,后期项目中最好用局部安装,不同项目使用的版本不同】
- 熟悉 npm基本命令确保npm可以使用
1.webpack概念
- 中文官网:https://www.webpackjs.com/
- Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
2.基本使用过程
-
新建项目文件夹最好不是中文
- 例如:
- └─src
│ index.js
└─js
format.js
math.js
│ index.html
│ package-lock.json
│ package.json
- └─src
- 例如:
-
package-lock与package.json区别:https://www.cnblogs.com/zxn-114477/p/15191044.html
-
src下的js下得两个js文件写入任意的code 例如 es6module commonjs…代码 在index.js中引入
- 直接在index.html引入index.js文件发现浏览器打开后无法识别,因此需要通过webpack打包
-
在当前项目目录下打开命令行,输入webpack 打包发现项目目录下生成dist文件 main.js,然后再index.html中使用就可以了
- 直接输入webpack使用的全局包 webpack的命令行
-
使用局部的命令行但是要使用 npm init生成package.json文件
-
npm install webpack webpack-cli -D
=>目录下生成 node_modules文件【存储的是安装的开发依赖包以及项目依赖包】 -
需要使用局部的webpack需要使用node_modules->.bin->webpack 可以在命令行中使用:./node_modules/.bin/webpack
或者使用 npx webpack命令
-
但是这种方式不太好,我们需要package.json文件里面“script”设置: 例如"build":“webpack”
-
然后再命令行中使用: npm run build 进行打包
-
默认情况下在打包时自动去找src目录下index.js文件,若我自己命了其他的名字或者目录需要指定某个文件为入口文件时,需要进行选项设置
例如需要修改package.json文件下得“script” “build”:“webpack --entry ./src/main.js …”
-
当然因为webpack的配置是很多的我们不可能将所有的配置项写入到 package.json文件内的script下
-
因此我们需要将webpack配置项单独成一个文件,因此在根目录下新建了名字为: webpack.config.js文件(默认名称)
- tips:默认配置文件名为webpack.config.js,否则使用“script” {“build”:"webpack --config 配置文件名“}
3.webpack的配置
-
因为webpack是用node的编写的所以我们使用 commonJS规范
-
在webpack.config.js文件中需要指定的选项可以参考官网
-
常见选项:
4. loader
loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
-
在你的应用程序中,有两种使用 loader 的方式:
-
module.rules允许我们配置多个loader
-
test
属性,识别出哪些文件会被转换。值为正则表达是 -
use
属性,定义出在进行转换时,应该使用哪个 loader。
常见的loader
01. css-loader
module: {
rules: [
{
test: /\.css$/, //以.css结尾的文件
//写法一:语法糖
loader: 'css-loader'
//写法二:
use:'css-loader'
//写法三:
use:['css-loader']
//写法四:完整写法
use:[
{
loader:"css-loader",
options:{
modules:true
}
}
]
},
]
}
02. style-loader
- css-loader解析.css的文件并不会插入到页面中,style-loader就是将css-loader处理后的内容插入到页面中
- 注意:loader的加载顺序是从后往前
03.处理less文件
npm i less less-loader -D
//webpack.config.js
rules: [
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
]
自行测试less文件
04.处理sass文件
npm i sass sass-loader -D
//webpack.config.js
rules: [
{
test: /\.s[ca]ss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
自行测试scss文件
05. postcss
PostCSS 本身是一个功能比较单一的工具。它提供了一种方式用JavaScript代码来处理CSS。利用PostCSS可以实现一些工程化的操作,如:自动添加浏览器前缀,代码合并,代码压缩等。
步骤:
-
安装:
npm install postcss postcss-cli -D
-
安装需要的依赖插件: 例如 autoprefixer(自动添加浏览器前缀)、postcss-preset-env、mini-css-extract-plugin(提取css)…
postcss-preset-env 允许开发者使用最新的 CSS 语法而不用担心浏览器兼容性。postcss-preset-env 会将最新的 CSS 语法转换为目标环境的浏览器能够理解的 CSS 语法。PostCSS 7 不支持 autoprefixer 8以上的版本.
postcss-preset-env 集成了 autoprefixer。
例如: npm i autoprefixer -D
执行命令:npx postcss --use autoprefixer -o 打包css文件名 输出的css文件名
tip:npx是自动会进入到node_modules内的bin文件下找到 postcss命令行运行
注意: npx postcss --use postcss-preset-env -o ./src/css/style.css ./src/css/test.css
报错:Input Error: You must pass a valid list of files to parse
postcss8不支持这种写法版本不兼容的问题 用之前的版本是可以的
-
在开发环境中使用postcss
// 在webpack.config.js中使用 module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1 }, }, { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'postcss-preset-env', { // 选项 }, ], ], }, }, }, ], }, ], }, }; 在postcss8中自己测试没有成功...
//在外部新建postcss.config.js进行配置 module.exports = { plugins: [ [ 'postcss-preset-env', { // Options }, ], ] } //webpack.config.js rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', "postcss-loader" ] } ] postcss8测试成功
06. 处理图片(file-loader | url-loader)
遇到 背景图、图片这些包webpack无法直接识别需要用到loader进行处理
module.exports = {
...
module:{
rules:[
{
test: /\.(jpe?g|png|gif|webp)$/,
use: {
loader: "file-loader",
options: {
name: "[name]_[hash:6].[ext]",
outputPath: "img"
}
}
}
]
}
...
}
遇到问题: 当前使用webpack5在下载file-loader@6.2 与 css-loader@6以上的版本进行 打包测试后发现 出现了两张图片资源一张加载错误一张ok,打包后使用的是加载错误的图片。
分析原因:在讲css设置的背景图处理后再交给css-loader处理出现的问题。
解决方案:将css-loader的版本降低到6以下。
url-loader:url-loader和file-loader的工作方式是相似的,但是可以将较小的文件,转成base64的URI
{
test: /\.(jpe?g|png|gif|webp)$/,
use: {
loader: "url-loader",
options: {
name: "[name]_[hash:6].[ext]",
outputPath: "img",
limit: 10 * 1024
}
}
}
07.资源模块(asset-modules)
资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。
在 webpack 5 之前,通常使用:
raw-loader
将文件导入为字符串url-loader
将文件作为 data URI 内联到 bundle 中file-loader
将文件发送到输出目录
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
asset/resource
发送一个单独的文件并导出 URL。之前通过使用file-loader
实现。asset/inline
导出一个资源的 data URI。之前通过使用url-loader
实现。asset/source
导出资源的源代码。之前通过使用raw-loader
实现。asset
在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用url-loader
,并且配置资源体积限制实现。
{
test: /\.(jpe?g|png|gif|webp)$/,
type: "asset",
generator: {
filename: "imgs/[name]_[hash][ext]"
},
parser: {
dataUrlCondition: {
maxSize: 10 * 1024
}
}
}
08.处理字体图标
用file-loader或者资源模块asset/resource
5.插件(Plugin)
loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。
01.cleanWeabpackPlugin
在webpack5之前我们需要使用cleanWeabpackPlugin插件,每次重新打包之前将之前的内容清除
npm i clean-webpack-plugin --save-dev
plugins:[
new CleanWebpackPlugin()
]
webpack5中只需要在output选项中设置:clean: true
02.htmlWeabpackPlugin
该插件将为你生成一个 HTML5 文件, 在 body 中使用
script
标签引入你所有 webpack 生成的 bundle
安装:npm install --save-dev html-webpack-plugin
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
inject: 'body',
title: "Vue App"
}),
]
配置项
-
title:生成的html文档的标题。配置该项,它并不会替换指定模板文件中的title元素的内容,除非html模板文件中使用了模板引擎语法来获取该配置项值,如下ejs模板语法形式:
<title><%= htmlWebpackPlugin.options.title %></title>
-
filename:输出文件的文件名称,默认为index.html,不配置就是该文件名;此外,还可以为输出文件指定目录位置(例如’html/index.html’)
1、filename配置的html文件目录是相对于webpackConfig.output.path路径而言的,不是相对于当前项目目录结构的。
2、指定生成的html文件内容中的link
和script
路径是相对于生成目录下的,写路径的时候请写生成目录下的相对路径 -
template:本地模板文件的位置,支持加载器(如handlebars、ejs、undersore、html等),如比如
handlebars!src/index.hbs
;1、template配置项在html文件使用
file-loader
时,其所指定的位置找不到,导致生成的html文件内容不是期望的内容。
2、为template指定的模板文件没有指定任何loader的话,默认使用ejs-loader
。如template: './index.html'
,若没有为.html
指定任何loader就使用ejs-loader
-
templateContent:string | function,可以指定模板的内容,不能与template共存。配置值为function时,可以直接返回html字符串,也可以异步调用返回html字符串。
-
inject:向template或者templateContent中注入所有静态资源,不同的配置值注入的位置不经相同
1、true或者body:所有JavaScript资源插入到body元素的底部
2、head: 所有JavaScript资源插入到head元素中
3、false: 所有静态资源css和JavaScript都不会注入到模板文件中 -
favicon:添加特定favicon路径到输出的html文档中,这个同
title
配置项,需要在模板中动态获取其路径值 -
hash: true|false,是否为所有注入的静态资源添加webpack每次编译产生的唯一hash值,添加hash形式如下所示:
html <script type="text/javascript" src="common.js?a3e1396b501cdd9041be"></script>
-
chunks:允许插入到模板中的一些chunk,不配置此项默认会将
entry
中所有的thunk注入到模板中。在配置多个页面时,每个页面注入的thunk应该是不相同的,需要通过该配置为不同页面注入不同的thunk; -
excludeChunks:这个与
chunks
配置项正好相反,用来配置不允许注入的thunk。 -
chunksSortMode: none | auto| function,默认auto; 允许指定的thunk在插入到html文档前进行排序。
值可以指定具体排序规则;auto基于thunk的id进行排序; none就是不排序 -
xhtml:rue|fasle, 默认false;是否渲染
link
为自闭合的标签,true则为自闭合标签 -
cache:true|fasle, 默认true; 如果为true表示在对应的thunk文件修改后就会emit文件
-
showErrors:true|false,默认true;是否将错误信息输出到html页面中。这个很有用,在生成html文件的过程中有错误信息,输出到页面就能看到错误相关信息便于调试。
-
minify:{…}|false;传递 html-minifier 选项给 minify 输出,false就是不使用html压缩,minify具体配置参数请点击html-minifier
配置多个html页面: new 多次
03.definePlugin
DefinePlugin是webpack注入全局变量的插件,通常使用该插件来判别代码运行的环境变量。在使用该插件需要注意的是,如果在该插件配置了相关的参数,必须要源码中使用,webpack才会注入。
04.copy-webpack-plugin
webpack的copy-webpack-plugin插件的作用是将项目中的某单个文件或整个文件夹在打包的时候复制一份到打包后的文件夹中
配置项:https://doc.codingdict.com/webpack-cn-doc/plugins/copy-webpack-plugin/
05 mode
https://zhuanlan.zhihu.com/p/134068206
06. devtool
07.babel
babel 在前端工程化开发中发挥着至关重要的作用,它能将较高级的语法转成浏览器可识别的代码,无论中 es6 中 const 、promise 还是 React、TypeScript。
//demo.js
const names = ["小明", "小花", "小爱"];
let newNames = names.map(item => "hello" + item)
命令行使用babel
babel 和之前说到的 postcss 一样,可以通过命令行运行,解析文件夹或者文件。安装命令行工具所需要的依赖,npm install @babel/cli @babel/core -D
通过 npx 执行 .bin 目录下的指令,–out-file 表示输出文件地址,执行编译语句 npx babel 文件目录 --out-file 输出位置
可我们发现,目标文件和源文件代码是一样的,const 和 箭头函数都没有被编译。因为,我们没有设置编译代码所需要的插件
上面代码中有标识符和箭头函数,需要【安装】并使用这些插件:
- 转换箭头函数:@babel/plugin-transform-arrow-functions
- 转换const:@babel/plugin-transform-block-scoping
插件需要通过 --plugins 添加在命令后面:
npx babel demo.js --out-dir lib --plugins @babel/plugin-transform-block-scoped-functions,@babel-plugin-transform-es2015-arrow-functions
var names = ["小明", "小花", "小爱"];
var newNames = names.map(function (item) {
return "hello" + item;
});
但插件只能实现单一功能,我们代码里一般也不只有 const 、箭头函数这种语法,当需要处理的代码种类变多,可能就要罗列出非常多的插件来执行,所以 babel 提供了一种插件的集合,叫做"预设","预设"会根据我们所配置的需要兼容处理的逻辑来进行编译。
预设
安装 @babel/preset-env
依赖后,在命令行使用 --presets 来替代 --plugins。npx babel src --out-file dist/presets.js --presets=@babel/preset-env
babel-loader
除了在命令行中直接通过 babel 编译文件,更多情况下会在项目中对批量文件进行处理,这时候就需要用到 babel-loader 来进行处理啦。
安装依赖 npm install babel-loader @babel/core @babel/preset-env -D
浏览器兼容
这里我们没有设置到底需要对什么样的浏览器进行兼容,使用的就是browserslist默认配置,browserslist作用及详细介绍
有两种方式可以设置babel兼容性处理的规则
browserslist:设置的兼容规则对css和js都通用,可配置在 .browserslist 或 package.json 文件中
targets:webpack.config.js 中配置在 loader 的options里
以上两种方式都可以配置,但更建议使用 browserslist,因为 css 和 js 需要兼容的浏览器版本一般来说是一致的,使用 browserslist 只需要配置一套规则即可。
比如我们设置 兼容谷歌浏览器版本99
// package.json
"browserslist": [
"chrome 99"
]
// 配置在 webpack.config.js 中
use: [
{
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
targets: ["chrome 99"],
},
],
],
},
},
],
https://gitcode.net/mirrors/browserslist/browserslist?utm_source=csdn_github_accelerator
polyfill
以上 babel 可以对于一些 js 语法进行处理,但有些新特性比如 promise 在默认情况下不会被处理,这样不能被低版本浏览器所识别。
那么我们需要借助"polyfill"来打补丁,对某些特定的语法做处理,这样编译后的代码中就能包含这些新特性。
- babel 7.4 以前,通过 @babel/polyfill
- babel 7.4 以后,通过 core-js regenerator-runtime
这里使用的 babel 版本是7.17,所以使用第二种方式,安装依赖 npm install core-js regenerator-runtime @babel/runtime-corejs3,在 babel.config.js 中给 preset 配置 polyfill 相关的属性
-
useBuiltIns:规定以什么方式来使用 polyfill
- false:不使用 polyfill,不用配置 corejs
- usage:自动检测源代码所需要使用的 polyfill,需配置corejs
- entry:导入所有 polyfill,文件体积很大,需配置corejs,以及在入口文件中引入 core-js 与 regenerator-runtime
-
corejs:所使用的 corejs 版本
// babel.config.js module.exports = { presets: [ [ "@babel/preset-env", { useBuiltIns: "entry", corejs: 3, }, ], ], };
然后
// 入口文件index.js import "core-js/stable"; import "regenerator-runtime/runtime"; // 或者 //webpack.config.js文件 module.exports = { entry: ['core-js/stable', 'regenerator-runtime/runtime', './src/index.js'], }
参考: 《来会会babel这个重要且神奇的工具》https://blog.csdn.net/bingbing1128/article/details/124654852
6.vue-loader
安装vue包(3.x):npm i vue -S
入口文件中引入: import {createApp} from ‘vue’
import { createApp } from 'vue'
const app = createApp({
template: "<h2>测试</h2>"
})
app.mount("#app")
npm run build
打开打完包的文件index.html,发现在控制台报警告
runtime-core.esm-bundler.js:167 [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias “vue” to “vue/dist/vue.esm-bundler.js”.
at
上面报出的警告意思是:组件中有template选项,但是运行时不支持。配置你的bundler别名 vue: vue/dist/vue.esm-bundler.js
解决方案:
- 1.在入口文件中引入vue时使用:
import { createApp } from 'vue/dist/vue.esm-bundler'
- 2.在webpack.config.js中配置
alias:{'vue$': 'vue/dist/vue.esm-bundler'}
完整版和运行时版
runtime
首先,runtime翻译过来就是运行时,在我找到的许多资料里显示,runtime版本没有编译器,不能使用template,只能使用render函数来渲染。配合使用了vue-loader,在webpack打包时,利用vue-loader来将template转化为了render函数
其次,因为没有编译器,所以runtime版本她体积小啊,适合浏览器更快的加载使用,而且vue默认使用runtime版本的
compiler
compiler版本翻译过来就是编译器,带有编译器的版本,可以使用template,编译器会把template转化为html由于带有编译器,体积就变大了,当然加载起来就会变慢,但是有一个疑问了,既然平时写vue的时候,是默认用runtime版的,而且也能使用template,那什么场景适用于使用编译器版本呢?常用于cdn引入模式,这种模式由于需要解析模板,所以需要引入完整版的vue
总之一句话,需要编译器进行解析模版的地方就使用compiler版本,不需要的就使用runtime版本
小结
1、runtime版本没有编译器
2、runtime版本比compiler版本体积小
3、runtime版本时vue默认版本
4、runtime版本本来不能使用template,但是由于使用webpack打包,所以配合vue-loader,将template转化为html
5、可以自己指定到底使用哪个版本,按需使用
Vue3.0版本区别
Vue3.0 中将 CJS、ESModule 和自执行函数分别打包到不同的文件中。在 packages/vue 中有 Vue3.0 的不同构建版本。
一共分为四类:
cjs(两个版本都是完整版本,包含了编译器)
commonjs 的模块化方式,都是完整版的,包含运行时和编译器.通过 require() 在 Node.js 服务器端渲染使用
- vue.cjs.js(开发版本,代码没有被压缩)
- Vue.cjs.prod.js(生产版本,代码被压缩了)
global(这四个文件都可以在浏览器中通过 script 标签中导入,导入后会添加一个全局的 vue 对象)
- vue.global.js(完整版的 vue,包含编译器和运行时,是开发版本,代码没有压缩)
- vue.global.prod.js(完整版的 vue,包含编译器和运行时,是生产版本,代码被压缩了)
- vue.runtime.global.js(只包含了运行时的构建版本,是开发版本,代码没有压缩)
- vue.runtime.global.prod.js(只包含了运行时的构建版本,是生产版本,代码被压缩了)
browser(这四个版本都使用 ESModule 的方式,浏览器的原生模块化方式,在浏览器中可以直接通过<script type="module" />
的方式来导入模块)
- vue.esm-browser.js
- vue.esm-browser.prod.js
- vue.runtime.esm-browser.js
- vue.runtime.esm-browser.prod.js
bundler(这两个版本没有打包所有的代码,只会打包使用到的代码,需要配合打包工具来使用,会让 vue 代码体积更小)
- vue.esm-bundler.js 是完整版的,包含运行时和编译器的ESModule版本。所有它内部还导入了
runtime-compiler
。 - vue.runtime.esm-bundler.js 是只包含运行时的构建版本,我们使用vue cli脚手架工具创建的项目中,默认导入使用的就是vue.runtime.esm-bundler.js,也就是它是vue的一个最小版本。在项目开发完毕后,重新打包的时候,只会打包我们使用到的代码。它可以让vue的体积更小。
使用vue文件
-
需要我们先下载vue-loader处理vue文件。
npm i vue-loader -D
-
在src下新建App.vue文件写入符合sfc的代码
-
在webpack.config.js中配置:
{ test: /\.vue$/, loader: "vue-loader" }
-
npm run build
发现报错: 其中提示-vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config. -
因此,我们需要在webpack.config.js导入VueLoaderPlugin
- const { VueLoaderPlugin } = require(‘vue-loader/dist/index’)
- plugins:[new VueLoaderPlugin()]
- vue-loader中需要使用@vue/compiler-sfc下载即可
-
运行则就成功
-
控制台还有一个警告:
Feature flags __VUE_OPTIONS_API__, __VUE_PROD_DEVTOOLS__ are not explicitly defined. You are running the esm-bundler build of Vue, which expects these compile-time feature flags to be globally injected via the bundler config in order to get better tree-shaking in the production bundle.
For more details, see https://link.vuejs.org/feature-flags.
需要在webpack.config.js中配置:
new DefinePlugin({
__VUE_OPTIONS_API__: true,//对vue2的optionsApi是否支持 若都是用的是vue3:setup 设置为false则通过tree_shaking 打包体积会更小
__VUE_PROD_DEVTOOLS__: false //在生产中启用/禁用 devtools 支持,默认值:false
}),
7.开发服务器
webpack-dev-server 可以提供用于开发的 HTTP Server(开发服务器),它已集成了自动编译和自动刷新页面的功能。
npm i webpack-dev-server -D
devServer: {
static: {
directory: path.join(__dirname, "dist"),
},
open: true,
port: 9000,
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '' },
},
},
},
static.directory : 告诉开发时可直接访问到 ./public(默认) 下的静态资源,这些资源在开发中不必打包。 webpack5以前是contentBase
open: 是否自动打开浏览器(默认为false)。
port: 服务端口,这里设置的9000,那么需要访问loaclhost:9000来访问打包好的页面。
proxy:现在,对 /api/users 的请求会将请求代理到 http://localhost:3000/users。
hot:热更新
import "./js/test.js"
if (module.hot) {
module.hot.accept('./js/test.js', () => {
console.log("更新后如何处理")
}, () => {
console.log("错误处理")
})
}
默认开启后vue文件自动热更新
开发环境启动:
//package.json
"scripts": {
"serve": "webpack serve"
}
8.开发环境与生产环境区分
"scripts": {
"build": " webpack --env production --config ./build/webpack.prod.config.js",
"serve": "webpack serve --env development --config ./build/webpack.dev.config.js"
},
webpack.config.js:
module.exports = (env, argv) => {
通过参数env进行区别
}
- 利用cross-env
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config ./build/webpack.prod.config.js",
"serve": "cross-env NODE_ENV=development webpack serve --config ./build/webpack.dev.config.js"
},
在node环境下进行环境判断
const isProEnv = () => process.env.NODE_ENV === "production";
在浏览器环境下也可以访问
9.配置分开
webpack.common.config.js
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')
// webpack内置的DefinePlugin
const { DefinePlugin } = require('webpack')
//copy-webpack-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { VueLoaderPlugin } = require('vue-loader/dist/index')
console.log(process.env.NODE_ENV);
const isProEnv = () => process.env.NODE_ENV === "production";
//打包进度条
const chalk = require("chalk");
const ProgressBarPlugin = require("progress-bar-webpack-plugin");
module.exports = {
target: 'web',
entry: ['core-js/stable', 'regenerator-runtime/runtime', './src/main.js'],
output: {
path: path.resolve(__dirname, "../dist"), //需要绝对路径
filename: "js/[name].bundle.js",
},
module: {
rules: [
{
test: /\.css$/,
use: [
isProEnv() ? MiniCssExtractPlugin.loader : 'style-loader',
// MiniCssExtractPlugin.loader,
'css-loader',
"postcss-loader"
]
},
{
test: /\.less$/,
use: [isProEnv() ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', "postcss-loader", 'less-loader']
},
{
test: /\.s[ac]ss$/i,
use: [
// 将 JS 字符串生成为 style 节点
isProEnv() ? MiniCssExtractPlugin.loader : 'style-loader',
// 将 CSS 转化成 CommonJS 模块
'css-loader',
// 将 Sass 编译成 CSS
'sass-loader',
]
},
// {
// test: /\.(jpe?g|png|gif|webp)$/,
// use: {
// loader: "file-loader",
// options: {
// name: "[name]_[hash:6].[ext]",
// outputPath: "img"
// }
// }
// },
// {
// test: /\.(jpe?g|png|gif|webp)$/,
// use: {
// loader: "url-loader",
// options: {
// name: "[name]_[hash:6].[ext]",
// outputPath: "img",
// limit: 10 * 1024
// }
// }
// }
{
test: /\.(jpe?g|png|gif|webp)$/,
type: "asset",
generator: {
filename: "imgs/[name]_[hash][ext]"
},
parser: {
dataUrlCondition: {
maxSize: 10 * 1024
}
}
},
// {
// test: /\.js$/,
// exclude: /node_modules/,
// use: [
// {
// loader: "babel-loader",
// options: {
// presets: ["@babel/preset-env", {
// target: ["chrome 99"]
// }]
// }
// }
// ]
// }
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html',
inject: 'body',
title: "Vue App"
}),
new DefinePlugin({
BASE_URL: JSON.stringify('./'),
__VUE_OPTIONS_API__: true,//对vue2的optionsApi是否支持 若都是用的是vue3:setup 设置为false则通过tree_shaking 打包体积会更小
__VUE_PROD_DEVTOOLS__: false //在生产中启用/禁用 devtools 支持,默认值:false
}),
new ProgressBarPlugin({
format: `:msg [:bar] ${chalk.green.bold(":percent")} (:elapsed s)`,
}),
],
resolve: {
alias: {
'vue$': 'vue/dist/vue.runtime.esm-bundler',
"@": path.resolve(__dirname, "../src")
},
extensions: ['.js', '.tsx', '.vue', '.json'],
}
}
webpack.dev.config.js
const { merge } = require('webpack-merge')
const webpackCommonConfig = require('./webpack.common.config')
const path = require("path");
module.exports = merge(webpackCommonConfig, {
mode: "development",
devtool: 'source-map',
devServer: {
static: {
directory: path.resolve(__dirname, "../public"),
},
port: 8000,
hot: true,
open: true,
compress: true
//代理
// proxy:{
// "/api": {
// target: "http://...",
// pathRewrite: {
// "^/api": ""
// },
// secure: false,
// changeOrigin: true
// }
// }
}
})
webpack.prod.config.js
const { merge } = require('webpack-merge')
const CopyPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const webpackCommonConfig = require('./webpack.common.config')
const path = require("path");
// 压缩css代码
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = merge(webpackCommonConfig, {
mode: "production",
output: { clean: true },
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[id].css"
}),
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, '../public'),
to: './',
globOptions: {
ignore: ["**/index.html"]
}
}
]
}),
],
optimization: {
minimizer: [
// 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
// `...`,
new CssMinimizerPlugin(), //css蕊
],
},
})
package.json
{
"name": "1.basic_webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config ./build/webpack.prod.config.js",
"serve": "cross-env NODE_ENV=development webpack serve --config ./build/webpack.dev.config.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.19.3",
"@babel/core": "^7.19.6",
"@babel/plugin-transform-block-scoped-functions": "^7.18.6",
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.19.4",
"@babel/runtime-corejs3": "^7.20.0",
"@vue/compiler-sfc": "^3.2.41",
"babel-loader": "^9.0.0",
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
"chalk": "^4.1.2",
"copy-webpack-plugin": "^11.0.0",
"core-js": "^3.26.0",
"cross-env": "^7.0.3",
"css-loader": "^5.2.7",
"css-minimizer-webpack-plugin": "^4.2.2",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"mini-css-extract-plugin": "^2.6.1",
"postcss": "^8.4.18",
"postcss-cli": "^10.0.0",
"postcss-loader": "^7.0.1",
"postcss-preset-env": "^7.8.2",
"progress-bar-webpack-plugin": "^2.1.0",
"regenerator-runtime": "^0.13.10",
"sass": "^1.55.0",
"sass-loader": "^13.1.0",
"style-loader": "^3.3.1",
"url-loader": "^4.1.1",
"vue-loader": "^17.0.0",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"vue": "^3.2.41"
}
}
10.Vue CLI 脚手架
cli(Command-Line Interface) 命令行界面
安装:npm i @vue/cli -g
升级版本:npm update @vue/cli -g
检查版本:vue --version
创建项目: vue create 项目名称