前言
vue3.0曾经出了一段时间了,网上也有大量的实际教程可供参考。但从理论登程,因为开发的chrome插件须要降级到vue3.0,同时筹备换上ant-design-vue,因为没有应用vue-cli脚手架,在这个降级过程中还是踩了不少坑,于是将本人搭建整个我的项目的过程记录下来,如对大家有帮忙,防止少踩坑也是极好的。(没有vue-router是因为chrome插件用不上)
该文章记录日期为2020年11月23日,但我的项目理论搭建日期应该是在一周前左右。因为目前vue3.0刚出不久,包含其配套生态也还处于beta版本或者刚出RC版,后续可能呈现一些变动,该实际仅作为目前版本的参考。
顺带一提,若想用上vue3.0下比拟成熟的UI框架,目前除了ant-design-vue和vant并没有太多抉择,如Vuetify,Quasar等优良的UI框架都还没适配vue3.0,能够急躁等一等。
一、webpack5根底环境配置
1.在我的项目下新建一个package.json配置文件
npm init -y
2.装置webpack5,webpack-cli和webpack-dev-server
阐明一下,就在4天前和19天前,webpack和webpack-cli又更新了版本,webpack为5.6.0, webpack-cli为4.2.0。而我搭建时的版本为webpack 5.4.0
npm i webpack webpack-cli webpack-dev-server -D
这里呈现第一个坑,webpack-cli若为4.2.0版本,应用webpack-dev-server会报错Error: Cannot find module 'webpack-cli/bin/config-yargs'
,因为版本之间不兼容造成。
解决形式,临时将webpack-cli版本降为3.3.12
3.装置所需依赖
Less和CSS
因为咱们应用了ant-design, CSS预编译就用less。
npm i less less-loader css-loader style-loader -D
TypeScript
npm i typescript ts-loader -D
Babel
npm i @babel/core @babel/preset-env @babel/plugin-transform-runtime babel-loader babel-plugin-import -D
npm i @babel/runtime -S
Vue和Vuex(指定版本)
npm i vue@next vuex@4.0.0-rc.1
这里遇见第二个坑,之前的vue-template-compiler
模板编译在这个版本会报错,改用@vue/compiler-sfc
npm i vue-loader@16.0.0-rc.1 @vue/compiler-sfc -D
Ant-design-vue(需指定版本)
npm i ant-design-vue@2.0.0-beta.15 -S
相干webpack插件
npm i clean-webpack-plugin copy-webpack-plugin html-webpack-plugin mini-css-extract-plugin -D
二、新建我的项目文件
文件目录
--index.html--src --main.ts --shims-vue.d.ts --pages --App.vue --store --Actions.ts --Getters.ts --Mutations.ts --State.ts --index.ts --assets --imgs --xxx.png--tsconfig.json--webpack.dev.config.js--webpack.prod.config.js--package.json
index.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <div id="app"></div></body></html>
main.ts
import { createApp } from "vue";import box from "./pages/App.vue";import store from './store';import Button from 'ant-design-vue/lib/Menu';import 'ant-design-vue/dist/antd.less';const app = createApp(box);app.use(store).use(Button).mount('#app');
store/index.ts
import { createStore } from 'vuex';import state from './State';import mutations from './Mutations';import actions from './Actions';import getters from './Getters';const store = createStore({ state, mutations, actions, getters})export default store;
store/Mutations.ts
interface mutationObj { addCount: Function, [propName: string]: any}const mutations: mutationObj = { addCount(state) { state.counter += 1; }}export default mutations;
store/State.ts
interface stateObj { counter: number, [propName: string]: any}const state: stateObj = { counter: 0}export default state;
App.vue
<template> <div class="box"> {{ counter }} <a-button type="primary" @click="addCount">增加</a-button> </div></template><script lang="ts">import { computed } from "vue";import { useStore } from "vuex";export default { name: "App", // 组合API函数入口 setup() { const store: any = useStore(); const counter = computed(() => { return store.state.counter; }); const addCount = () => { store.commit("addCount"); }; return { counter, addCount }; },};</script><style lang="less" scoped>.box { width: 300px; height: 300px; background: red;}</style>
三、配置文件
webpack.dev.config.js
const path = require('path');const { HotModuleReplacementPlugin, IgnorePlugin } = require('webpack');const { CleanWebpackPlugin } = require('clean-webpack-plugin');const HtmlWebpackPlugin = require('html-webpack-plugin');const { VueLoaderPlugin } = require('vue-loader');const config = { mode: 'development', entry: './src/main.ts', output: { filename: 'index.js', path: path.resolve(__dirname, 'dist') }, devServer: { contentBase: false, // publicPath: './dist', hot: true, port: 8080, open: true, // hotOnly: true, compress: true, overlay: true }, watchOptions: { ignored: /node_modules/ }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Hot Module Replacement', template: 'index.html' }), new IgnorePlugin(/^\.\/locale$/, /moment$/), new HotModuleReplacementPlugin(), new VueLoaderPlugin() ], module: { rules: [ // babel应用runtime,防止将不须要的代码注入 { test: /\.js$/, exclude: /node_modules/, use: [{ loader: 'babel-loader', options: { // cacheDirectory: true, presets: ['@babel/preset-env'], plugins: [ '@babel/plugin-transform-runtime', ['import', { "libraryName": "antd", "style": true, // or 'css' }, 'antd'] ] } }], }, { test: /\.ts$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: { // 指定特定的ts编译配置,为了辨别脚本的ts配置 configFile: path.resolve(__dirname, './tsconfig.json'), appendTsSuffixTo: [/\.vue$/] } } ] }, { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: ['style-loader', 'css-loader'] }, { test: /\.less$/, use: ['style-loader', 'css-loader', { loader: 'less-loader', options: { lessOptions: { modifyVars: { 'primary-color': '#4608e2', 'link-color': '#4608e2', 'border-radius-base': '20px', }, javascriptEnabled: true, } } }], } ] }, resolve: { extensions: ['.js', '.ts'] },};module.exports = (env) => { console.log(`以后执行${env.mode}模式`); return config;}
webpack.prod.config.js
const path = require('path');const { CleanWebpackPlugin } = require('clean-webpack-plugin');const HtmlWebpackPlugin = require('html-webpack-plugin');const CopyWebpackPlugin = require('copy-webpack-plugin');const MiniCssExtractPlugin = require('mini-css-extract-plugin');const { VueLoaderPlugin } = require('vue-loader');const config = { mode: 'production', entry: './src/main.ts', output: { filename: 'index.js', path: path.resolve(__dirname, 'dist') }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'Hot Module Replacement', template: 'index.html' }), new CopyWebpackPlugin({ patterns: [ { from: 'src/assets', to: 'assets' }, ] }), new MiniCssExtractPlugin({ filename: './index.css' }), new VueLoaderPlugin() ], module: { rules: [ // babel应用runtime,防止将不须要的代码注入 { test: /\.js$/, exclude: /node_modules/, use: [{ loader: 'babel-loader', options: { cacheDirectory: true, presets: ['@babel/preset-env'], plugins: [ ['import', { "libraryName": "antd", "style": true, // or 'css' }, 'antd'] ] } }], }, { test: /\.ts$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: { // 指定特定的ts编译配置,为了辨别脚本的ts配置 configFile: path.resolve(__dirname, './tsconfig.json'), appendTsSuffixTo: [/\.vue$/] } } ] }, { test: /\.vue$/, use: ['vue-loader'] }, { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] }, { test: /\.less$/, use: [MiniCssExtractPlugin.loader, 'css-loader', { loader: 'less-loader', options: { lessOptions: { modifyVars: { 'primary-color': '#4608e2', 'link-color': '#4608e2', 'border-radius-base': '20px', }, javascriptEnabled: true, } } }] } ] }, resolve: { extensions: ['.js', '.ts'] },};module.exports = (env) => { console.log(`以后执行${env.mode}模式`); return config;}
tsconfig.json
{ "compilerOptions": { // "esModuleInterop": true, "incremental": true, // 增量编译 "allowJs": true, "lib": [ "es6", "dom", "es2017" ], "types": [] }, "exclude": [ "node_modules" ]}
shims-vue.d.ts
declare module '*.vue' { import Vue from 'vue'; export default Vue;}declare module "vue/types/vue" { interface Vue { $http: any; $Message: any; $Modal: any; }}
package.json
{ "name": "test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --config webpack.dev.config.js --env.mode development --watch --profile", "build": "webpack --config webpack.prod.config.js --env.mode production" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@babel/core": "^7.12.9", "@babel/plugin-transform-runtime": "^7.12.1", "@babel/preset-env": "^7.12.7", "@vue/compiler-sfc": "^3.0.2", "babel-loader": "^8.2.1", "babel-plugin-import": "^1.13.3", "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^6.3.2", "css-loader": "^5.0.1", "html-webpack-plugin": "^4.5.0", "less": "^3.12.2", "less-loader": "^7.1.0", "mini-css-extract-plugin": "^1.3.1", "style-loader": "^2.0.0", "ts-loader": "^8.0.11", "typescript": "^4.1.2", "vue-loader": "^16.0.0-rc.1", "webpack": "^5.6.0", "webpack-cli": "^3.3.12", "webpack-dev-server": "^3.11.0" }, "dependencies": { "@babel/runtime": "^7.12.5", "ant-design-vue": "^2.0.0-beta.15", "vue": "^3.0.2", "vuex": "^4.0.0-rc.1" }}
四、命令执行
开发环境
npm start
生产环境
npm run build
五、最终成果
六、结语
这个我的项目搭建的案例,只做了最简略的示例,就是利用vuex做一个计数器。其实chrome插件会有多个入口文件,最终打包进去的文件构造和开发时还是有所区别,前面会独自写篇文章介绍。
我将该示例放在了github上,欢送食用~
https://github.com/gxy5202/we...