问题描述
限时送ChatGPT账号..所以基本上,我正在尝试为 MVC 项目创建一个混合结构.前端框架将由 Webpack 和 VueJS 管理.然而,经过数周的修补和与 Vue 一起学习正确的 Webpack 知识后,我一直无法实现我想要的.
所以上面是项目结构,但特别是 webpack 层.webpack文件夹首先会被Webpack打包到wwwroot/dist文件夹中,最终会是这样;
从这里,我们将能够将包导入到 MVC 视图的主布局中,然后我们可以将 Vue 内联应用于每个视图.这样做的目标是,我们可以首先,
使用 Webpack 捆绑样式和常用 js 库能够利用 Vue 和 Vue 的组件,同时能够创建块结构(0.js、1、2 ....)由于 2,我们将能够向 CSR(客户端渲染)倾斜.这是我的 webpack.config.js 供参考.
const path = require('path');const webpack = require('webpack');const MergeIntoSingleFilePlugin = require('webpack-merge-and-include-globally');const UglifyJsPlugin = require('uglifyjs-webpack-plugin');const ExtractTextPlugin = require('extract-text-webpack-plugin');const extractCSS = new ExtractTextPlugin('bundle.css');//声明多个模块//https://stackoverflow/questions/16631064/declare-multiple-module-exports-in-node-jsmodule.exports = 函数(环境){环境 = 环境 ||{};var isProd = env.NODE_ENV === '生产';//为所有环境设置基本配置变量配置 = {入口: {主:'./Webpack/js/main'},输出: {//输出文件的格式文件名:'[名称].js',//将文件放入wwwroot/js/"路径:path.resolve(__dirname, 'wwwroot/dist/')},开发工具:'评估源地图',解决: {别名:{'vue': 'vue/dist/vue.esm.js'//使用完整构建},扩展名:['.js', '.jsx']},插件: [提取CSS,新的 webpack.ProvidePlugin({$: "jquery",jQuery: "jquery","window.jQuery": "jquery'","window.$": "jquery","dt": "datatables",波普尔:['popper.js','默认']}),新的 MergeIntoSingleFilePlugin({文件:{//表相关库tbl.js":['node_modules/datatables/js/jquery.dataTables.js','node_modules/datatables-bs4/js/dataTables.bootstrap4.js'],tbl.css":['node_modules/datatables-bs4/css/dataTables.bootstrap4.css','node_modules/datatables-buttons-bs4/css/buttons.bootstrap4.min.css'],双网.js":['Webpack/js/securo/Duo-Web-v2.js']}})],模块: {规则: [{ 测试:/\.css$/,使用:extractCSS.extract(['css-loader?minimize']) },{ 测试:/\.(png|jpg|jpeg|gif|svg)$/, 使用: 'url-loader?limit=25000' },{ 测试:/\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, 使用: 'url-loader?limit=100000' },//识别VueJS{测试:/\.vue$/,loader: 'vue-loader'},//全局公开 jQuery//https://stackoverflow/questions/47469228/jquery-is-not-defined-using-webpack{测试:require.resolve('jquery'),用: [{装载机:'暴露装载机',选项:'jQuery'},{装载机:'暴露装载机',选项:'$'}]},{测试:require.resolve('bootbox'),用: [{装载机:'暴露装载机',选项:引导箱"}]},{测试:require.resolve('clipboard'),用: [{装载机:'暴露装载机',选项:剪贴板"}]},],装载机: [{测试:/\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,装载机:网址装载机"},{测试:/\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,装载机:网址装载机"},{测试:/\.vue$/,loader: 'vue-loader'}]}};//更改生产环境的配置如果(isProd){config.devtool = '源图';config.plugins = config.plugins.concat([新的 UglifyJsPlugin({源地图:真实}),//https://vuejs/v2/guide/deployment.html新的 webpack.DefinePlugin({'process.env':{NODE_ENV: '"生产"'}})]);}返回配置;};函数 toObject(路径){var ret = {};路径.forEach(函数(路径){ret[path.split('/').slice(-1)[0]] = path;});返回 ret;}
这里是 main.js
//先加载css导入 'bootstrap/dist/css/bootstrap.css';导入'../css/counter-ui.css';导入'../css/site.css';导入 'font-awesome/css/font-awesome.css';//然后js从'vue'导入Vue;//编译包含的构建 https://github/nuxt/nuxt.js/issues/1142导入'jquery';导入'jquery-validation';导入'jquery-validation-unobtrusive';导入'popper.js';导入引导程序";导入引导日期选择器";导入引导箱";导入剪贴板";导入'magicsuggest';进口'nouislider';导入'../js/counter-ui.js';导入'formcache';//Vue 组件Vueponent(/* webpackChunkName: "base-select" */'base-select', () => import('./components/base-select.vue'));//全局暴露Vue//https://stackoverflow/questions/45388795/uncaught-referenceerror-vue-is-not-defined-when-put-vue-setting-in-index-html窗口.Vue = Vue;$(函数(){$('.datepicker').datepicker();$('.dropdown-toggle').dropdown();$('[data-toggle="popover"]').popover({动画:真实,});});//数组重复过滤器//https://stackoverflow/questions/6940103/how-do-i-make-an-array-with-unique-elements-i-e-remove-duplicates函数 OmitArrDupes(a) {var temp = {};for (var i = 0; i < a.length; i++)temp[a[i]] = 真;var r = [];for (var k in temp)r.push(k);返回 r;}
如您所见,webpack 仅用于捆绑常用库和样式,同时,它用于存储 Vue 和我将要制作的组件,并帮助完成所有繁琐的工作.
>你最终会得到:
这就是你如何能像我一样陷入困境,或者就我所知,像我一样愚蠢.在将其用于生产用途后,我正在变成一个退化者.
根据 chrome 上的控制台错误判断,0.js 已加载但由于组件方面的原因中止.那么究竟是怎么回事呢?我真的很想知道这实际上是如何工作的.以前从未如此深入地了解前端.
EDIT 这可能是由于组件的语法.可能是错的?嗯.. 但如果是这样的话,Webpack 就没有话题了.
<div :class="{ __disabled: disabled }" class="dropdown"><button @click="toggle" class="btn btn-primary dropdown-toggle">{{ currOption.name }}按钮><div v-if="opened" class="下拉菜单"><div v-for="o in options" :value="getVal(value)" @click="change(o)" :class="{__active: getVal(o) == getVal(value)}" class="dropdown_item">{{ getLabel(o) }}</div></模板><脚本>导出默认{名称:基础选择",数据() {返回 {打开:假,currOption:{}}},方法: {getVal(选择){返回 !this.valueKey ?选择:选择[this.valueKey];},获取标签(选择){返回 !this.labelKey ?选择:选择[this.labelKey];},改变(选择){this.$emit('input', opt)this.opened = false;如果(this.onChange !== 未定义){this.onChange(this.value);}},切换(){如果(this.disabled){返回}//翻动this.opened = !this.opened;}},道具: {价值: {要求:真实},选项: {类型:数组,要求:真实},值键:{类型:字符串,要求:假},标签键:{类型:字符串,要求:假},onChange:{类型:功能,要求:假},禁用:{类型:布尔型,默认值:假}}}<样式范围></风格>
UPDATE 2 试图创建一个 test.vue 组件,它有一个带有 hi 的模板
也没有用.同样的错误.
解决方案除了@skribe 所说的,
Vueponent('base-select', () => import('./components/base-select.vue').then(m => m.default));
这应该全局公开所有组件.为了支持 .NET Core 调用的路由,您必须添加一个名为 publicPath 的附加参数.publicPath 允许您相对于您声明的根公共路径全局公开文件,在本例中为 publicPath.
module.exports = function (env) {环境 = 环境 ||{};var isProd = env.NODE_ENV === '生产';//为所有环境设置基本配置变量配置 = {入口: {主:'./Webpack/js/main'},输出: {//输出文件的格式文件名:'[名称].js',//将文件放入wwwroot/js/"路径:path.resolve(__dirname, 'wwwroot/dist/'),//============ 添加下面的行 ==============//公共路径:'/dist/'},
So basically, I'm trying to make a hybrid structure for an MVC project. The frontend framework will be managed by Webpack and VueJS. However, after weeks of tinkering and picking up proper Webpack knowledge together with Vue, i've been unable to achieve what I want to do so.
So right above is the project structure, but specifically the webpack layer. The webpack folder will first be packed by Webpack into the wwwroot/dist folder, which would end up like this;
From here, we'll be able to import the bundles into the main layout of the MVC's view which we can then apply Vue inline to each and every view. The goal in doing this is such that we can first,
Bundle styles and commonly used js libraries with Webpack Be able to utilize Vue and Vue's components while being able to create a chunk structure (0.js, 1, 2 ....) Because of 2, we'll be able to lean abit towards CSR (Client Side Rendering).Here's my webpack.config.js for reference.
const path = require('path');
const webpack = require('webpack');
const MergeIntoSingleFilePlugin = require('webpack-merge-and-include-globally');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractCSS = new ExtractTextPlugin('bundle.css');
// Declaring multiple modules
// https://stackoverflow/questions/16631064/declare-multiple-module-exports-in-node-js
module.exports = function (env) {
env = env || {};
var isProd = env.NODE_ENV === 'production';
// Setup base config for all environments
var config = {
entry: {
main: './Webpack/js/main'
},
output: {
// The format for the outputted files
filename: '[name].js',
// Put the files in "wwwroot/js/"
path: path.resolve(__dirname, 'wwwroot/dist/')
},
devtool: 'eval-source-map',
resolve: {
alias: {
'vue': 'vue/dist/vue.esm.js' // Use the full build
},
extensions: ['.js', '.jsx']
},
plugins: [
extractCSS,
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery'",
"window.$": "jquery",
"dt": "datatables",
Popper: ['popper.js', 'default']
}),
new MergeIntoSingleFilePlugin({
files: {
// Table related libraries
"tbl.js": [
'node_modules/datatables/js/jquery.dataTables.js',
'node_modules/datatables-bs4/js/dataTables.bootstrap4.js'
],
"tbl.css": [
'node_modules/datatables-bs4/css/dataTables.bootstrap4.css',
'node_modules/datatables-buttons-bs4/css/buttons.bootstrap4.min.css'
],
"duo-web.js": [
'Webpack/js/securo/Duo-Web-v2.js'
]
}
})
],
module: {
rules: [
{ test: /\.css$/, use: extractCSS.extract(['css-loader?minimize']) },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' },
{ test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' },
// Recognise VueJS
{
test: /\.vue$/,
loader: 'vue-loader'
},
// Expose jQuery globally
// https://stackoverflow/questions/47469228/jquery-is-not-defined-using-webpack
{
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]
},
{
test: require.resolve('bootbox'),
use: [{
loader: 'expose-loader',
options: 'bootbox'
}]
},
{
test: require.resolve('clipboard'),
use: [{
loader: 'expose-loader',
options: 'Clipboard'
}]
},
],
loaders: [
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url-loader"
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url-loader"
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
}
};
// Alter config for prod environment
if (isProd) {
config.devtool = 'source-map';
config.plugins = config.plugins.concat([
new UglifyJsPlugin({
sourceMap: true
}),
// https://vuejs/v2/guide/deployment.html
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
})
]);
}
return config;
};
function toObject(paths) {
var ret = {};
paths.forEach(function (path) {
ret[path.split('/').slice(-1)[0]] = path;
});
return ret;
}
And here's the main.js
// Load the css first
import 'bootstrap/dist/css/bootstrap.css';
import '../css/counter-ui.css';
import '../css/site.css';
import 'font-awesome/css/font-awesome.css';
// Then the js
import Vue from 'vue'; // Compile included builds https://github/nuxt/nuxt.js/issues/1142
import 'jquery';
import 'jquery-validation';
import 'jquery-validation-unobtrusive';
import 'popper.js';
import 'bootstrap';
import 'bootstrap-datepicker';
import 'bootbox';
import 'clipboard';
import 'magicsuggest';
import 'nouislider';
import '../js/counter-ui.js';
import 'formcache';
// Vue Components
Vueponent(/* webpackChunkName: "base-select" */ 'base-select', () => import('./components/base-select.vue'));
// Expose Vue globally
// https://stackoverflow/questions/45388795/uncaught-referenceerror-vue-is-not-defined-when-put-vue-setting-in-index-html
window.Vue = Vue;
$(function() {
$('.datepicker').datepicker();
$('.dropdown-toggle').dropdown();
$('[data-toggle="popover"]').popover({
animation: true,
});
});
// Array Dupes Filter
// https://stackoverflow/questions/6940103/how-do-i-make-an-array-with-unique-elements-i-e-remove-duplicates
function OmitArrDupes(a) {
var temp = {};
for (var i = 0; i < a.length; i++)
temp[a[i]] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
}
As you can see, webpack is just solely used for bundling common libraries and styles while at the same time, it's used to store Vue and the components i'll be making, and help out with all the dirty work.
You will then eventually end up with:
And that is how you'll be able to get stuck like me, or as far as know, stupid as me. I'm turning into a degen after picking this up for production use.
Judging by the console errors on chrome, 0.js loaded but aborted because of the component side of things. So what exactly is going on? Am really curious to know how this is actually working. Have never been so deep into frontend before.
EDIT It could be due to the component's syntax. Might be wrong? hmm.. But if that's the case, Webpack would be out of the topic.
<template>
<div :class="{ __disabled: disabled }" class="dropdown">
<button @click="toggle" class="btn btn-primary dropdown-toggle">
{{ currOption.name }}
</button>
<div v-if="opened" class="dropdown-menu">
<div v-for="o in options" :value="getVal(value)" @click="change(o)" :class="{__active: getVal(o) == getVal(value)}" class="dropdown_item">{{ getLabel(o) }}</div>
</div>
</div>
</template>
<script>
export default {
name: "base-select",
data() {
return {
opened: false,
currOption: {}
}
},
methods: {
getVal(opt) {
return !this.valueKey ? opt : opt[this.valueKey];
},
getLabel(opt) {
return !this.labelKey ? opt : opt[this.labelKey];
},
change(opt) {
this.$emit('input', opt)
this.opened = false;
if (this.onChange !== undefined) {
this.onChange(this.value);
}
},
toggle() {
if (this.disabled) {
return
}
// flip
this.opened = !this.opened;
}
},
props: {
value: {
required: true
},
options: {
type: Array,
required: true
},
valueKey: {
type: String,
required: false
},
labelKey: {
type: String,
required: false
},
onChange: {
type: Function,
required: false
},
disabled: {
type: Boolean,
default: false
}
}
}
</script>
<style scoped>
</style>
UPDATE 2 Attempted to create a test.vue component, which has a template with a hi
Didn't work either. Same error.
解决方案Apart from what @skribe said,
Vueponent('base-select', () => import('./components/base-select.vue').then(m => m.default));
That should expose all components globally. In order to support the routings called by .NET Core, you have to add an additional parameter called publicPath. publicPath allows you to globally expose files relatively to a root public path that you have declared, which in this case is publicPath.
module.exports = function (env) {
env = env || {};
var isProd = env.NODE_ENV === 'production';
// Setup base config for all environments
var config = {
entry: {
main: './Webpack/js/main'
},
output: {
// The format for the outputted files
filename: '[name].js',
// Put the files in "wwwroot/js/"
path: path.resolve(__dirname, 'wwwroot/dist/'),
// ============ ADD THE LINE BELOW ============= //
publicPath: '/dist/'
},
这篇关于通过 Webpack 暴露全局 Vue 组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论