最近由于业务需要,要重新开始构建一个 vue 的 H5 项目
我这个人一直很喜欢用新版本的东西,所以 Vue-Cli4
Webpack5
Typescript
通通安排上!!!
为什么不用 Vue3 呢,因为个人感觉这 3.x 版本现在还不太适合投入生产 【我绝对不会承认是因为自己菜学不动 Vue3的....】
我对这个项目的期望是有如下几点:
- 使用 Vue-cli4 / Webpack5 来构建项目
- 引入 Typescript
- 引入 Eslint
- 使用 gzip / image 压缩等
- 自适应布局 amfe-flexible / postcss-pxtorem
- 引入 vant-ui,并配置按需引入
So! 下面开始进入正题吧!
初始化项目
安装 Vue-cli4
首先我们需要用 vue -V
这个命令行查看本机的是否安装了 vue-cli,或者 vue-cli 的版本是否为 4.x 版本
如果已经安装,但是版本太低了就删掉重新安装就好啦
npm uninstall vue-cli -g
然后再次
npm install @vue/cli -g
安装完成后再次使用 vue -V
命令查看版本,4.x 的版本就可以继续下面的操作啦。
初始化项目
vue create #你的项目名#
使用 vue 的 create 命令来构建项目,比如 vue create my-app
接下来就会出现自定义配置的选项啦~
首先这里我们选择第三个:Manually select features
然后勾选自己需要的模块,我勾选的是:
Babel / TypeScript / Router / Vuex / CSS Pre-processors / Lint
如上图所示~
接下来就是让你选择你想使用的 vue 的版本【我卑微的选择了 2.x】
然后是选择路由的模式,不选择 History 模式的原因是找后端配置太麻烦啦,自己搞定比较好
最后一个问题:是否保留本次的配置,这样下次初始化项目的时候可以直接使用,我选择的不【毕竟下一次新建项目估计就是有新玩意儿了呢~~~
好啦,这样我们就初始化好啦~
进入项目运行起来就能看到熟悉的欢迎页~
依赖安装
自 vue-cli 的 3.x 和 webpack4.x 版本后,就不再有各种配置文件啦,取而代之是一个 vue.config.js
文件
由于需要增加 pxtorem 的配置和 vant 组件的按需引入,以及各种压缩插件,我会在后面直接献上最终的配置文件:
首先我们需要安装各种依赖啦:
// 自适应布局的
npm install postcss-pxtorem -D
npm install amfe-flexible
// 压缩图片的和各种 loader
cnpm install image-webpack-loader --save-dev
cnpm install pngquant-bin --save-dev
npm install imagemin-gifsicle --save-dev
npm install imagemin-mozjpeg --save-dev
npm install imagemin-optipng --save-dev
npm install imagemin-pngquant --save-dev
npm install compression-webpack-plugin --save-dev
// 注意这里的 image-webpack-loader 和 pngquant-bin 一定要使用 cnpm 安装,使用 npm 会导致项目报错无法运行
// 安装 vant ui 和它的按需引入插件
npm i vant -S
// 这个是按需引入的插件
npm i ts-import-plugin --save-dev
好啦,各种依赖安装完毕,接下来就是文件配置了:
文件配置
vue.config.js
vue.config.js
// vue.config.js
const path = require('path');
const CompressionWebpackPlugin = require('compression-webpack-plugin'); // 开启gzip压缩, 按需引用
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i; // 开启gzip压缩, 按需写入
const merge = require('webpack-merge');
const tsImportPluginFactory = require('ts-import-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
.BundleAnalyzerPlugin; // 打包分析
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV);
const resolve = dir => path.join(__dirname, dir);
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/site/vue-demo/' : '/',
// 公共路径
indexPath: 'index.html',
// 相对于打包路径index.html的路径
outputDir: process.env.outputDir || 'dist',
// 'dist', 生产环境构建文件的目录
assetsDir: 'static',
// 相对于outputDir的静态资源(js、css、img、fonts)目录
lintOnSave: false,
// 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码
runtimeCompiler: true,
// 是否使用包含运行时编译器的 Vue 构建版本
productionSourceMap: !IS_PROD,
// 生产环境的 source map
// parallel: require('os').cpus().length > 1,
parallel: false,
// 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
pwa: {},
chainWebpack: config => {
config.resolve.symlinks(true); // 修复热更新失效
// 如果使用多页面打包,使用vue inspect --plugins查看html是否在结果数组中
config.plugin('html').tap(args => {
// 修复 Lazy loading routes Error
args[0].chunksSortMode = 'none';
return args;
});
config.resolve.alias // 添加别名
.set('@', resolve('src'))
.set('@assets', resolve('src/assets'))
.set('@components', resolve('src/components'))
.set('@views', resolve('src/views'))
.set('@store', resolve('src/store'));
// 压缩图片
// 需要 npm i -D image-webpack-loader
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
bypassOnDebug: true
}).end();
config.module
.rule('ts')
.use('ts-loader')
.tap(options => {
options = merge(options, {
happyPackMode: true,
transpileOnly: true,
getCustomTransformers: () => ({
before: [
tsImportPluginFactory({
libraryName: 'vant',
libraryDirectory: 'es',
// 这句必须加上,不然修改主题没有效果
style: name => `${name}/style/less`
})
]
}),
compilerOptions: {
module: 'es2015'
}
})
return options
});
// 打包分析, 打包之后自动生成一个名叫report.html文件(可忽视)
if (IS_PROD) {
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [{
analyzerMode: 'static'
}]);
}
},
configureWebpack: config => {
// 开启 gzip 压缩
// 需要 npm i -D compression-webpack-plugin
const plugins = [];
if (IS_PROD) {
plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8
})
);
}
config.plugins = [...config.plugins, ...plugins];
},
css: {
extract: IS_PROD,
requireModuleExtension: true, // 若为 false,可能导致按需引入的 vant 样式不生效
loaderOptions: {
less: {
// `globalVars` 定义全局对象,可加入全局变量
globalVars: {
primary: '#333'
},
},
postcss: {
plugins: [
require('autoprefixer')({
// 配置使用 autoprefixer
overrideBrowserslist: ['last 15 versions']
}),
//如果个别地方不想转化px。可以简单的使用大写的 PX 或 Px 。
require('postcss-pxtorem')({
rootValue: 37.5, // 换算的基数
propList: ['*'],
//exclude: /node_modules/ //配置无需转换
})
]
}
}
},
devServer: {
overlay: {
// 让浏览器 overlay 同时显示警告和错误
warnings: true,
errors: true
},
host: 'localhost',
port: 8080,
// 端口号
https: false, // https:{type:Boolean}
open: false, //配置自动启动浏览器
hotOnly: true, // 热更新
proxy: {
//配置多个跨域
// '/api': {
// target: 'http://xxx.xxx',
// changeOrigin: true,
// // ws: true,//websocket支持
// secure: false,
// pathRewrite: {
// '^/api': '/'
// }
// },
}
}
};
直接复制进去就可以,每个字段配置都有相应的解释,如果碰到说有依赖缺失就再次 install 就好啦
tsconfig.json
tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
babel.config.js
babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
}
main.ts
main.ts
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import 'amfe-flexible/index.js'; // flex布局
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app');
这样就差不多配置好啦!!
我的项目结构和 package.json如下图所示:
这样子一个项目就基本搭建好啦,如果中途又遇到什么问题欢迎评论一起讨论哦