I crated a new .net core project using the SPA template from https://github.com/MarkPieszak/aspnetcore-Vue-starter#getting-started
with dotnet new vuejs
After restoring packages with npm install I could sucesully open the project and run it from Visual Studio.
I now wanted to use a single file component by adding a file about.vue in /ClientApp/components/about/.
I changed app.ts to use
#Component({
components: {
MenuComponent: require('../navmenu/navmenu.vue.html'),
AboutComponent: require('../about/about.vue')
}
})
When I now run the application I get the error
ERROR in ./ClientApp/components/about/about.vue
Module parse failed: C:\playground\vue-journey\ClientApp\components\about\about.vue Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| <template>
| <div class="about">
| <h1>This is an about page</h1>
# ./~/awesome-typescript-loader/dist/entry.js?silent=true!./ClientApp/components/app/app.ts 30:28-57
# ./ClientApp/components/app/app.vue.html
# ./ClientApp/boot.ts
# multi event-source-polyfill webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.ts
I did not change the webpack.config because to me it looks like it has the required loader.
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const bundleOutputDir = './wwwroot/dist';
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
return [{
stats: { modules: false },
context: __dirname,
resolve: { extensions: [ '.js', '.ts' ] },
entry: { 'main': './ClientApp/boot.ts' },
module: {
rules: [
{ test: /\.vue\.html$/, 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' ] : ExtractTextPlugin.extract({ use: 'css-loader?minimize' }) },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
]
},
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: 'dist/'
},
plugins: [
new CheckerPlugin(),
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 ExtractTextPlugin('site.css')
])
}];
};
What do I have to do to compile single file components?
Edit
The file component itself only contains a template and it works in a project I created with vue cli.
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
From the documentation, it appears you're missing the Vue loader plugin.
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
plugins: [
new VueLoaderPlugin()
]
}
The project was created with a different template then what I thought
I actually used dotnet new vuejs
not dotnet new vue. Stuff like that happens around midnight.
Related
With the following webpack.common.js:
const pathtoresolve = require('path');
const paths = require('./paths')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
// Where webpack looks to start building the bundle
entry: [ 'whatwg-fetch', paths.src + '/main.js'],
resolve: {
extensions: [ '.js', '.vue' ],
alias: {
'components': pathtoresolve.resolve(__dirname, '../src/components/'),
'images': pathtoresolve.resolve(__dirname, '../src/images/'),
'styles': pathtoresolve.resolve(__dirname, '../src/styles/'),
}
},
// Where webpack outputs the assets and bundles
output: {
path: paths.build,
filename: '[name].bundle.js',
publicPath: '/',
},
// Customize the webpack build process
plugins: [
// Vue plugin for the magic
new VueLoaderPlugin(),
// Removes/cleans build folders and unused assets when rebuilding
new CleanWebpackPlugin(),
// Copies files from target to destination folder
new CopyWebpackPlugin({
patterns: [
{
from: paths.public,
to: 'assets',
globOptions: {
ignore: ['*.DS_Store'],
},
},
],
}),
// Generates an HTML file from a template
// Generates deprecation warning: https://github.com/jantimon/html-webpack-plugin/issues/1501
new HtmlWebpackPlugin({
title: 'webpack Boilerplate',
favicon: paths.src + '/images/favicon.png',
// TODO This isn't returning HTML. What did it return??
template: '!!vue-loader!' + paths.src + '/App.vue', // template file (explicitly vue)
filename: 'index.html', // output file
}),
],
// Determine how modules within the project are treated
module: {
rules: [
// JavaScript: Use Babel to transpile JavaScript files
{test: /\.vue$/, loader: 'vue-loader' },
{test: /\.js$/, exclude: /node_modules/, use: ['babel-loader']},
// Styles: Inject CSS into the head with source maps
{
test: /\.(scss|css)$/,
use: [
// Note: Only style-loader works for me !!!
// 'vue-style-loader',
'style-loader',
{loader: 'css-loader', options: {sourceMap: true, importLoaders: 1}},
{loader: 'postcss-loader', options: {sourceMap: true}},
{loader: 'sass-loader', options: {sourceMap: true}},
],
},
// Images: Copy image files to build folder
{test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource'},
// Fonts and SVGs: Inline files
{test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline'},
],
},
}
I get the error:
$ yarn run client-build && yarn run serve
$ node client/build/app.js
building for production...
assets by status 751 KiB [cached] 4 assets
Entrypoint main = js/runtime.06de30f0b0451051a1b0.bundle.js styles/main.3b829f3c5154760383f9.css js/main.ec103c819b2711f469d3.bundle.js
ERROR in unable to locate 'D:\IdeaProjects\AIPlatform\oml\api\client\public' glob
ERROR in Error: The loader "D:\IdeaProjects\AIPlatform\oml\api\client\src\App.vue" didn't return html.
My vue template looks like:
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
But the vue loader was invoked explicitly, so should be returning HTML from my Vue template.
This is using webpack#^5.8.0, html-webpack-plugin#^5.4.0, vue-loader#^15.9.8, and vue-template-compiler#^2.6.14 . (package.json would have been included, except StackOverflow refuses to allow posts that are too dense with code.)
My goal here is to get a html file out of this vue file using webpack. Any suggestions?
Any suggestions?
In my app I'm initializing a Vue app, which uses single file .vue components.
I use Webpack to bundle, and vue-loader + postcss-modules to generate scoped classes.
But for some reason I can't access the generated classes inside my components ($style object is empty). I'll explain the problem below and created this repo as an example.
My hello.vue component looks like this:
<template>
<div :class="$style.hello">
Hello World!
</div>
</template>
<script>
export default {
name: "hello",
created() {
console.log(this.$style); // <- empty object :(
}
};
</script>
<style module>
.hello {
background: lime;
}
</style>
hello.vue.json is generated as expected (CSS Modules mapping):
{"hello":"_hello_23p9g_17"}
Scoped styles are appended in the document head, and when using mini-css-extract-plugin it is bundled in app.css:
._hello_23p9g_17 {
background: lime;
}
Does anyone know what the problem is and possibly how to fix this?
Below my config files.
webpack.config.js (trimmed for readability)
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
module.exports = {
entry: {
app: "./src/index.js"
},
output: {
filename: "[name].js",
path: path.resolve(__dirname, "build")
},
resolve: {
extensions: [".js", ".vue", ".json", ".css"],
alias: {
vue: "vue/dist/vue.esm.js"
}
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader"
}
},
{
test: /\.vue$/,
loader: "vue-loader"
},
{
test: /\.css$/,
use: [
"vue-style-loader",
// MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
// modules: true,
importLoaders: 1
}
},
"postcss-loader"
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: "[name].css"
}),
new VueLoaderPlugin()
]
};
postcss.config.js
module.exports = {
ident: "postcss",
plugins: {
"postcss-preset-env": { stage: 0 },
"postcss-modules": {}
}
};
EDIT:
FYI, setting modules: true in the css-loader options works in that it populates the $style object (see docs):
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true
}
}
]
}
But in our app we use postcss-loader (as per docs) that takes care of all transformations including scoping. Enabling both modules: true and postcss-modules conflicts and breaks the classes/mapping (as expected).
In other words, I'm looking for a way to omit the modules: true option and enable css modules using postcss-modules instead.
Found a workaround: manually import the styles from the JSON file.
If anyone knows a better way please let me know :)
hello.vue.json
{"hello":"_hello_fgtjb_30"}
hello.vue
<template>
<div :class="style.hello">
Hello World!
</div>
</template>
<script>
import style from "./hello.vue.json";
export default {
name: "hello",
beforeCreate() {
this.style = style;
},
created() {
console.log(this.style);
}
};
</script>
<style module>
.hello {
background: lime;
}
</style>
This only works when using postcss-modules (loaded from config by postcss-loader in my case) instead of using modules: true:
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
importLoaders: 1
}
},
"postcss-loader"
]
};
See this PR as a full example.
webpack.base.conf.js
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: 'vue-style-loader!css-loader!sass-loader',
sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
}
}
},
{
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/assets/scss/_variables.scss')
}
},
My "variables" file starts to load, but then i get this error:
Module parse failed: Unexpected character '#' (1:8)
You may need an appropriate loader to handle this file type.
| $white: #ffffff;
|
| // The Vue build version to load with the `import` command
I use this manual:
https://vue-loader-v14.vuejs.org/en/configurations/pre-processors.html
vue version: 2.93
Eventually i created project from scratch using vue-cli#3
and added to vue.config.js this code:
const path = require('path');
module.exports = {
chainWebpack: config => {
const oneOfsMap = config.module.rule('scss').oneOfs.store
oneOfsMap.forEach(item => {
item
.use('sass-resources-loader')
.loader('sass-resources-loader')
.options({
resources: [
path.resolve(__dirname, './src/assets/scss/_variables.scss'),
path.resolve(__dirname, './src/assets/scss/_mixins.scss'),
]
})
.end()
})
}
}
You might want to add it to a vue.config.js file in your root directory. If the file doesn't exist, create it and add something along the lines of this (my config):
module.exports = {
css: {
loaderOptions: {
sass: {
data: `
#import "#/assets/_variables.scss";
`
}
}
}
};
I have setup vuejs with webpack 4 and it's working fine now I have added auth0 file in my vuejs application and include it into the login page view It may be a webpack issue as in console the export default not working. Whenever I tried to work with vue-cli it works fine as well in the example. I want it with a webpack 4.
ERROR in ./src/auth/AuthService.js
Module parse failed: Unexpected token (7:16)
You may need an appropriate loader to handle this file type.
|
| export default class AuthService {
| authenticated = this.isAuthenticated()
| authNotifier = new EventEmitter()
|
# ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/views/session/Login.vue 59:0-49
# ./src/views/session/Login.vue
# ./src/router/index.js
# ./src/index.js
# multi (webpack)-dev-server/client?http://localhost:8080 babel-polyfill ./src/index.js
This is my login vue file.
<template>
<div>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Auth0 - Vue</a>
<router-link :to="'/'"
class="btn btn-primary btn-margin">
Home
</router-link>
<button
class="btn btn-primary btn-margin"
v-if="!authenticated"
#click="login()">
Log In
</button>
<button
class="btn btn-primary btn-margin"
v-if="authenticated"
#click="logout()">
Log Out
</button>
</div>
</div>
</nav>
<div class="container">
<router-view
:auth="auth"
:authenticated="authenticated">
</router-view>
</div>
</div>
</template>
<script>
import AuthService from './auth/AuthService'
const auth = new AuthService()
const { login, logout, authenticated, authNotifier } = auth
export default {
name: 'app',
data () {
authNotifier.on('authChange', authState => {
this.authenticated = authState.authenticated
})
return {
auth,
authenticated
}
},
methods: {
login,
logout
}
}
</script>
<style>
#import 'bootstrap/dist/css/bootstrap.css';
.btn-margin {
margin-top: 7px
}
</style>
And this is my webpack config file.
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
// plugins
const HtmlWebPackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
// the path(s) that should be cleaned
let pathsToClean = [
'dist'
]
// the clean options to use
let cleanOptions = {
root: __dirname,
verbose: false, // Write logs to console.
dry: false
}
// Webpack uses `publicPath` to determine where the app is being served from.
// In development, we always serve from the root. This makes config easier.
const publicPath = '/';
// Make sure any symlinks in the project folder are resolved:
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: ["babel-polyfill", "./src/index.js"],
output: {
// The build folder.
path: resolveApp('dist'),
// Generated JS file names (with nested folders).
// There will be one main bundle, and one file per asynchronous chunk.
// We don't currently advertise code splitting but Webpack supports it.
filename: 'static/js/[name].[chunkhash:8].js',
chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath: publicPath
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
contentBase: false,
compress: true,
port: 8080 // port number
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/img/[name].[hash:7].[ext]'
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'media/[name].[hash:7].[ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'media/fonts/[name].[hash:7].[ext]'
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
{
test: /\.scss$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
},
{
loader: "sass-loader"
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(pathsToClean, cleanOptions),
new HtmlWebPackPlugin({
template: "./index.html",
filename: "./index.html",
favicon: './static/favicon.png'
}),
new CopyWebpackPlugin([{
from: 'static/img',
to: 'static/img'
}]),
new MiniCssExtractPlugin({
filename: "static/css/[name].[contenthash:8].css",
chunkFilename: "static/css/[name].[contenthash:8].css"
}),
//jquery plugin
new webpack.ProvidePlugin({
$: 'jquery',
jquery: 'jquery',
'window.jQuery': 'jquery',
jQuery: 'jquery'
})
]
}
I had the same error, and I resolved it translating AuthService.js Module in Babel:
https://babeljs.io/repl
However, is not the solution that everybody want, so, you can try:
Unable to load stage-3 javascript file using babel-loader from webpack
I do not resolved with this solution.
I am using vue of typescript as well as typescript in Express. Everything worked until i want to use single file component in vue.js.
Here is my component,
<template>
<div>This is a simple component. {{msg}}</div>
</template>
<script lang='ts'>
export default {
data() {
return {
msg: "you"
}
}
}
</script>
My webpack file,
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPugPlugin = require('html-webpack-pug-plugin');
const Webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: {
bundle: [
'./node_modules/bootstrap/dist/js/bootstrap.js',
'./dist/web/views/common/client/ts/_main.js',
'./web/views/common/client/style/main.scss'
]
},
output: {
path: path.resolve(__dirname, 'public'),
filename: '[name].js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
ts: 'ts-loader'
},
esModule: true
}
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {
minimize: false
}
}, {
loader: 'sass-loader'
}]
})
},
{
test: require.resolve('jquery'),
loader: 'expose-loader?$!expose-loader?jQuery'
}
]
},
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js'
}
},
plugins: [
new ExtractTextPlugin('styles.css'),
new HtmlWebpackPlugin({
template: './web/views/common/_layout.pug',
filename: '../web/views/common/layout.pug',
filetype: 'pug'
}),
new HtmlWebpackPugPlugin(),
new Webpack.ProvidePlugin({
jQuery: 'jquery',
$: 'jquery',
Popper: 'popper.js'
})
]
};
If I don't use single file component, everything works, but when i introduce .vue file, it will show this error,
ERROR in ./dist/web/views/about/client/ts/_aboutController.js
Module not found: Error: Can't resolve './components/mycomponent.vue' in '/Users/george/github/bochure/dist/web/views/about/client/ts'
# ./dist/web/views/about/client/ts/_aboutController.js 4:24-63
# ./dist/web/views/common/client/ts/_main.js
# multi ./node_modules/bootstrap/dist/js/bootstrap.js ./dist/web/views/common/client/ts/_main.js ./web/views/common/client/style/main.scss
Can anyone help me? You can also download my source at github and help me out. Many thanks.
git#github.com:geforcesong/bochure.git
I'd suggest you to check the component path first.
If you are embedding one vue component into another then check if both are on the same directory level.
If they are then you can use './component-name.vue' and you will be good to go.
Try to change
'./components/mycomponent.vue'
'../components/mycomponent.vue'
This might work in some cases.