改造AspNetCore的Vue模板:匹配Ant Design of Vue

AspNetCore有一套Spa模板Microsoft.AspNetCore.SpaTemplates,可以用来快速生成Spa项目。
尝试了一下其中的Vue模板,使用起来挺方便的,Vue+TypeScript作为前端,AspNetCore作为后端,能生成一个简单的Vue应用。
但是这个模板已经很久没有更新了,集成的控件是Bootstrap,想改为使用Ant Design of Vue,要费一番功夫。

准备工作

安装模板
dotnet new --install Microsoft.AspNetCore.SpaTemplates::*
使用模板创建Vue项目
dotnet new vue
会以当前文件夹名为项目命名

修改目标框架

模板默认是基于.NetCore2.0的,已经过时,所以将将目标框架改为3.1。
修改后会提示错误,需要修改项目文件,将ItemGroup节的PackageReference子节点删除,等待VS还原项目
然后手动添加Microsoft.AspNetCore.SpaServices的Nuget包
此时在Startup.cs文件中会报warnning。需要修改Configure方法,将env参数的类型改为IWebHostEnvironment,然后修改ConfigureServices方法,在services.AddMvc中增加options.EnableEndpointRouting = false的选项。修改后代码如下:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options => options.EnableEndpointRouting = false);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //代码未变动,中间仍有一个warnning,但没办法消除
}

更新NPM包

模板自带的NPM包版本都很低,安装AntDesign后无法正常使用,需要进行更新,但直接更新为最新版会带来版本兼容性问题。经过测试,最终的package.json文件如下

{
  "name": "project-name",
  "private": true,
  "version": "0.0.0",
  "devDependencies": {
    "@types/webpack-env": "^1.15.3",
    "ant-design-vue": "^1.7.2",
    "aspnet-webpack": "^3.0.0",
    "awesome-typescript-loader": "^5.2.1",
    "css-loader": "^5.0.1",
    "event-source-polyfill": "^1.0.21",
    "file-loader": "^6.2.0",
    "isomorphic-fetch": "^3.0.0",
    "jquery": "^3.1.1",
    "mini-css-extract-plugin": "^1.3.0",
    "postcss": "^8.1.0",
    "style-loader": "^2.0.0",
    "typescript": "^3.9.7",
    "url-loader": "^4.1.1",
    "vue": "^2.6.12",
    "vue-class-component": "^7.2.6",
    "vue-loader": "^15.9.5",
    "vue-property-decorator": "^9.0.2",
    "vue-router": "^3.4.9",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^4.27.0",
    "webpack-cli": "^4.2.0",
    "webpack-dev-middleware": "^3.0.0",
    "webpack-hot-middleware": "^2.25.0"
  }
}

除了版本更新外,还进行了以下更改:去除Bootstrap,将extract-text-webpack-plugin替换为mini-css-extract-plugin。同时,还需要修改webpack.config.jswebpack.config.vendor.js文件

//webpack.config.js
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const bundleOutputDir = './wwwroot/dist';

module.exports = (env) => {
    const isDevBuild = !(env && env.prod);

    return [{
        mode:isDevBuild?'development':'production',
        stats: { modules: false },
        context: __dirname,
        resolve: {
            extensions: ['.js', '.ts'],
            alias: {
                'vue$': 'vue/dist/vue.esm.js'
            }
        },
        entry: { 'main': './ClientApp/boot.ts' },
        module: {
            rules: [
                { test: /\.vue$/, include: /ClientApp/, loader: 'vue-loader', options: { loaders: { js: 'awesome-typescript-loader?silent=true' } } },
                { test: /\.ts$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
                { test: /\.css$/, use: isDevBuild ? [ 'style-loader', 'css-loader' ] : [MiniCssExtractPlugin.loader, 'css-loader?minimize' ] },
                { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' },
                { test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },
            ]
        },
        output: {
            path: path.join(__dirname, bundleOutputDir),
            filename: '[name].js',
            publicPath: 'dist/'
        },
        plugins: [
            new CheckerPlugin(),
            new VueLoaderPlugin(),
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: JSON.stringify(isDevBuild ? 'development' : 'production')
                }
            }),
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./wwwroot/dist/vendor-manifest.json')
            })
        ].concat(isDevBuild ? [
            // Plugins that apply in development builds only
            new webpack.SourceMapDevToolPlugin({
                filename: '[file].map', // Remove this line if you prefer inline source maps
                moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
            })
        ] : [
            // Plugins that apply in production builds only
            new webpack.optimize.UglifyJsPlugin(),
            new MiniCssExtractPlugin('site.css')
        ])
    }];
};

//webpack.config.vendor.js
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = (env) => {
    const isDevBuild = !(env && env.prod);
    return [{
        stats: { modules: false },
        resolve: {
            extensions: ['.js'],
        },
        entry: {
            vendor: [
                'event-source-polyfill',
                'isomorphic-fetch',
                'vue/dist/vue.esm.js',
                'vue-router'
            ],
        },
        module: {
            rules: [
                { test: /\.(sa|sc|c)ss$/, use: [MiniCssExtractPlugin.loader, isDevBuild ? 'css-loader' : 'css-loader?minimize' ] },
                { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' }
            ]
        },
        output: { 
            path: path.join(__dirname, 'wwwroot', 'dist'),
            publicPath: 'dist/',
            filename: '[name].js',
            library: '[name]_[hash]'
        },
        plugins: [
            new MiniCssExtractPlugin({ filename: 'vendor.css' }),
            new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': isDevBuild ? '"development"' : '"production"'
            }),
            new webpack.DllPlugin({
                path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'),
                name: '[name]_[hash]'
            })
        ].concat(isDevBuild ? [] : [
            new webpack.optimize.UglifyJsPlugin()
        ])
    }];
};

最后,在修改入口文件boot.ts。新版的vue-loader在通过require导入组件时需要加上.default(参考此处),最终的boot.ts文件为

//boot.ts
import './css/site.css';
import Vue from 'vue';
import VueRouter, { RouteConfig } from 'vue-router';
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
Vue.config.productionTip = false;

Vue.use(Antd);
Vue.use(VueRouter);

const routes:RouteConfig[] = [
    { path: '/', component: require('./components/home/home.vue').default },
    { path: '/counter', component: require('./components/counter/counter.vue').default },
    { path: '/fetchdata', component: require('./components/fetchdata/fetchdata.vue').default },

new Vue({
    el: '#app-root',
    router: new VueRouter({ mode: 'history', routes: routes }),
    render: h => h(require('./components/app/app.vue').default)
});

这样,AntDesign就能正常使用了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值