基本上,我正在尝试为MVC项目制作混合结构。前端框架将由Webpack和VueJS管理。然而,经过数周的修补和与Vue一起获得适当的Webpack知识后,我一直无法实现我想要的目标。
所以上面是项目结构,但特别是webpack层。 webpack文件夹首先由Webpack打包到wwwroot / dist文件夹中,最终会像这样;
从这里开始,我们将能够将包导入到MVC视图的主要布局中,然后我们可以将Vue内联应用于每个视图。这样做的目标是我们可以首先,
这是我的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');
// Declaring multiple modules
// https://stackoverflow.com/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.net",
Popper: ['popper.js', 'default']
}),
new MergeIntoSingleFilePlugin({
files: {
// Table related libraries
"tbl.js": [
'node_modules/datatables.net/js/jquery.dataTables.js',
'node_modules/datatables.net-bs4/js/dataTables.bootstrap4.js'
],
"tbl.css": [
'node_modules/datatables.net-bs4/css/dataTables.bootstrap4.css',
'node_modules/datatables.net-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.com/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.org/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;
}
这是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.com/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
Vue.component(/* webpackChunkName: "base-select" */ 'base-select', () => import('./components/base-select.vue'));
// Expose Vue globally
// https://stackoverflow.com/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.com/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;
}
正如您所看到的,webpack仅用于捆绑常见的库和样式,同时,它用于存储Vue和我将要制作的组件,并帮助解决所有肮脏的工作。
然后你最终会得到:
这就是你如何能像我一样陷入困境,或者据我所知,愚蠢。在将其用于生产用途后,我正在变成一个degen。
根据chrome上的控制台错误判断,由于组件方面的问题,加载了0.js但是已中止。到底是怎么回事?我真的很想知道这是如何实际工作的。从来没有如此深入到前端。
编辑这可能是由于组件的语法。可能是错的?嗯..但如果是这样的话,Webpack将不在话题中。
<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>
更新2 尝试创建一个test.vue组件,其中包含一个带有hi的模板
也没用。同样的错误。
答案 0 :(得分:1)
我认为这可能是由最近为vue-loader更改的异步/动态导入语法引起的,现在使用“... ES模块在内部利用webpack 3范围提升”。 (请参阅下面的发行说明)
尝试像这样导入
Vue.component('base-select', () => import('./components/base-select.vue').then(m => m.default));
https://github.com/vuejs/vue-loader/releases/tag/v13.0.0
编辑尝试将输出块文件名更改为相对路径,如下所示。
output: {
// The format for the outputted files
filename: '[name].js',
// Put the files in "wwwroot/js/"
path: path.resolve(__dirname, 'wwwroot/dist/')
// Set chuck file name
chunkFilename:'../../js/[name].bundle.js'
},
答案 1 :(得分:1)
除了@skribe所说的,
Vue.component('base-select', () => import('./components/base-select.vue').then(m => m.default));
这应该在全球范围内公开所有组件。为了支持.NET Core调用的路由,您必须添加一个名为 publicPath 的附加参数。 publicPath允许您相对于已声明的根公共路径全局公开文件,在本例中为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/'
},