前言
最近在复习webpack的知识,觉得光看不练是学不好webpack的,所以有了手动搭建一个Vue3+Ts运行环境的想法。废话不多说,直接开始进行搭建。
创建文件夹,并且进入该目录
生成package.json文件
如果你的目录名字是合法的,可以直接加上-y
。这代表所有的选项都选择yes。
npm init
安装webpack,webpack-cli
这里的webpack和webpack-cli在开发环境需要,而在生成环境是不需要的。所以加上-D
npm install webpack webpack-cli -D
在package.json中创建脚本
我们可以直接在命令行通过npx webpack进行打包,但是我们也可以通过在package.json文件中,创建一个build脚本,这样就可以通过npm run build
执行打包操作了。
创建webpack配置文件
默认情况下在根目录下创建webpack.config.js文件,即可对webpack进行配置。但是考虑到后面配置的命令可能会比较多。所以这里对webpack的配置文件进行了拆分。在根目录下创建一个webpack_config文件夹,在该文件夹下,创建三个文件:webpack.common.js(进行通用配置的文件),webpack.dev.js(进行开发环境配置的文件),webpack.prod.js(进行生产环境配置的文件)。
因为默认情况下,webpack会去读取webpack.config.js文件的配置,而这里我们的并不是在改文件进行配置,所以我们需要指定配置文件的目录。我们直接在package.json文件中的脚本命令那里设置即可。
对webpack.common.js文件进行配置如下
const path = require('path')
module.exports = {
entry: './src/main.js', // 设置打包的入口文件,这里不需要../。因为这里是相对于context的,而context的路径就是根目录。
output: {
path: path.resolve(__dirname, '../bundle'), // 这里需要../ ,因为这里不是相对于context。
publicPath: '/', 配置打包后index.html引入资源的前缀
filename: 'js/[name].[chunkhash:6].bundle.js',
clean: true // 在打包之前,先将打包的文件删除掉。
}
}
处理css,less文件
安装css-loader进行css文件的处理,安装style-loader(将样式通过style标签插入到html中)。
安装less-loader对less文件进行处理。
安装postcss-loader,postcss-preset-env(这个是一个插件),用于对css文件添加浏览器前缀。
npm install css-loader style-loader less-loader postcss-loader postcss-preset-env -D
进行配置
// 在webpack.common.js中
module.exports = {
...
module: {
rules: [
{
test: /\.css$/, // 匹配css文件
use: [
"style-loader",
{
loader: "css-loader",
options: {
importLoaders: 1, // css-loader前还有几个loader
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: { // 对postcss的配置也可以单独抽离到一个文件中,这里就不抽取了。
plugins: ['postcss-preset-env'],
}
},
},
],
},
{
test: /\.less$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env']
}
}
},
'less-loader'
]
}
],
},
处理图片以及字体资源
在webpack5处理这些资源可以直接使用asset module type进行处理,不需要安装file-loader或者url-loader进行处理。
进行配置
// webpack.common.js
module.exports = {
...
module: {
rules: [
{
test: /\.(jpe?g|svg|png)$/, // 匹配的资源
type: 'asset', // asset,结合了file-loader和url-loader的功能
generator: {
filename: 'img/[name].[hash:6][ext]' // 生成的文件名
},
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 当生成的图片小于10kb,则不会生成图片,会转成base64
}
}
},
{
test: /\.(tff|woff|ttf)$/,
type: "asset",
generator: {
filename: "fonts/[name].[hash:6][ext]",
},
parser: {
dataUrlCondition: {
maxSize: 8 * 1024,
},
},
},
]
}
}
生成html文件
到目前为止,我们打包后的文件是没有html文件的。如果我们想要在打包后生成html文件,我们可以使用html-webpack-plugin帮助我们进行html文件的生成。该生成的html会自动帮助我们进行文件的引入。
安装html-webpack-plugin。
npm install html-webpack-plugin -D
在使用该plugin时,我们可以为它指定一个html的模板,也可以让它自动为我们生成html文件
进行配置
// webpack.common.js
const HtmlWebpackPlugin = require('html-webpack-plugin') // 导入该插件
module.exports = {
...
plugins: [
new HtmlWebpackPlugin() // 如果需要对该插件进行进一步的配置,可以自行查找资料
]
}
创建一个服务
在进行vue开发时,我们会执行npm run serve创建一个本地服务。在webpack中,如果想要创建一个本地服务,需要安装webpack-dev-server
npm install webpack-dev-server -D
在package.json文件中创建一个脚本
然后执行npm run serve即可开启一个本地服务。
创建了本地服务后,我们可以对本地服务进行一些配置。而这些配置是在开发是才会用到的,在打包时是不需要用到的,所以这里对之前的配置进行分离。
进行配置文件的分离
首先在执行脚本时,可以传入一个参数,这样我们就可以判断当前是要使用开发配置还是使用生产配置。
当我们的配置文件导出的是一个函数时,webpack会将我们传入的参数作为函数的参数传递给我们,我们就可以根据这个参数来决定使用哪些配置。
除了获取到配置模式,我们还需要将配置命令进行合并。可以使用webpack-merge插件来帮助我们完成配置的合并。
npm install webpack-merge -D
// webpack.common.js
const { merge } = require('webpack-merge') // 获取merge函数
const commonConfig = {} // 这个对象保存着之前的配置
module.exports = (env) => {
// 判断当前的模式
const mode = env.production ? 'production' : 'development'
let config = null
// 根据不同模式,导入不同配置
if (mode === 'production') {
config = require('./webpack.prod')
} else {
config = require('./webpack.dev')
}
// 返回合并后的配置文件
return merge(commonConfig, config)
}
配置devServer
// webpack.dev.js
module.exports = {
mode: 'development',
devtool: 'cheap-module-source-map', // 设置source-map文件,便于开发代码调试
devServer: {
hot: true, // 开启模块热替换,默认就是开启的
historyApiFallback: { // 处理路由 history 模式刷新页面丢失
rewrites: [
{
from: /\.*/, // 匹配所有的路径
to: '/index.html' // 映射到index.html文件中
}
]
}
}
}
处理js文件
在打包的时候,为了做浏览器的适配,我们需要对ES6+的js装换成ES5的代码。这个时候我们就可以使用babel来帮助我们装换。
安装babel-loader @babel/core @babel/preset-env。
npm install @babel/core @babel/preset-env @babel-loader -D
进行配置
因为对js代码的适配,只需要在打包的时候进行转换即可。在开发过程中,没有必要对代码进行转换,所以这里只在prod文件进行配置即可。
module.exports = {
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, // 不处理node_modules下的js文件,这样就不会消耗打包时间
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
}
处理ts文件
处理ts文件我们可以通过babel-loader和@babel/preset-typescript来处理,也可以通过ts-loader来处理。这里我采用开发时使用,ts-loader这样可以对一下ts错误进行检测。打包时采用babel-loader,这样可以对转换后的js做一下兼容处理。
使用ts-loader是必须要有tsconfig.json文件,如果没有可以在终端使用tsc --init。如果报错,在全局安装typescript即可。
npm install @babel/preset-typescript ts-loader typescript -D
进行配置
开发环境下配置
// webpack.dev.js
module.exports = {
...
module: {
rules: [
{
test: /\.ts$/,
exclude: /\.ts$/,
use: {
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/], // 处理在vue文件中使用ts
transpileOnly: true, // 关闭类型检测,这样可以减少编译时间。
}
}
}
]
}
}
在上面的配置中,我们关闭了类型检测,以减少编译时间,我们可以将类型检测的职责交给另一个插件来帮助我们完成,这个插件会开启另一个线程来帮助我们进行类型检测。
安装fork-ts-checker-webpack-plugin插件
npm install fork-ts-checker-webpack-plugin -D
在上面的配置的基础上加上该插件的使用即可。
// webpack.dev.js
const ForkTsCheckerWebapckPlugin = require('fork-ts-checker-webpack-plugin')// 导入该插件
module.exports = {
...
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/], // 处理在vue文件中使用ts
transpileOnly: true, // 关闭类型检测,这样可以减少编译时间。
}
}
}
]
}
plugins: [
new ForkTsCheckerWebpackPlugin()
]
}
生成环境下配置
// webpack.prod.js
module.exports = {
...
module: {
rules: [
{
test: /\.ts$/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
['@babel/preset-typescript', {
// 这个配置是为了处理.vue文件解析后的ts文件
allExtensions: true
}]
]
}
}
}
]
}
}
处理.vue文件
处理 .vue文件 需要安装 vue-loader和@vue/compiler-sfc。 因为当前处理的是vue3的文件,而vue3还没有作为默认版本,所以需要安装vue-loader@next,当vue3成为默认版本的时候就直接安装即可。
npm install @vue/compiler-sfc vue-loader@next -D**
因为不论是在开发环境还是生成环境,都需要对 .vue文件 进行处理。所以这里将.vue文件的处理配置放在了webpack.common.js文件中。
进行配置
const { VueLoaderPlugin } = require('vue-loader') // 导入VueLoaderPlugin
module.exports = {
...
module: {
rules: [
{
test: /\.vue$/,
exclude: /node_modules/,
loader: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin() // 这里要使用这个插件
]
}
打包后,运行时会发现会有如下警告
这个警告的意思是,vue强烈推荐我们自己定义__VUE_OPTION_API_,VUE_PROD_DEVTOOLS 这两个变量,这两个变量一个是决定要不要使用optionsAPI,一个是决定要不要启用Devtools插件。我们可以根据自己的情况进行定义。
在webpack中如何定义全局变量呢,我们可以通过webpack内置的DefinePlugin插件来进行定义。
// webpack.common.js
const { DefinePlugin } = require('webpack')
module.exports = {
...
plugins:[
new DefinePlugin({
__VUE__OPTION_API__: false,
__VUE_PROD__DEVTOOLS: true
})
]
}
进行完上面的全局变量的定义,再次打开就会发现没有上面的警告了。
总结
通过上面的基本配置,我们就可以运行vue3和ts的项目了。接下来还需要对该项目进行一些优化,将在之后进行处理。