So i am trying to update my vue-loader in laravel project to version 15.2.1. After updating dependencies and running npm run watch first i get an error that i shoul use VueLoaderPlugin. I added it like official documentation suggests.
After trying to run build command again i get this error for each one of my single file components:
ERROR in ./node_modules/css-loader!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/sass-loader/lib/loader.js!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/users/User.vue?vue&type=style&index=0&id=d0ee1f54&scoped=true&lang=sass
Module build failed:
<template lang="pug">
^
Invalid CSS after "": expected 1 selector or at-rule, was ".user-container"
in C:\MAMP\htdocs\lightCRM\resources\assets\js\components\users\User.vue (line 1, column 1)
@ ./node_modules/style-loader!./node_modules/css-loader!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/sass-loader/lib/loader.js!./node_modules/vue-loader/lib??vue-loader-options!./resources/assets/js/components/users/User.vue?vue&type=style&index=0&id=d0ee1f54&scoped=true&lang=sass 4:14-338
@ ./resources/assets/js/components/users/User.vue?vue&type=style&index=0&id=d0ee1f54&scoped=true&lang=sass
@ ./resources/assets/js/components/users/User.vue
@ ./resources/assets/js/routes/routes.js
@ ./resources/assets/js/app.js
@ multi ./resources/assets/js/app.js
If iam adding this rule to my laravel-mix config
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
Then compilation runs successfully, but in console I get:
[vue warn]: failed to mount component: template or render function not defined.
I use sass and pug in my vue components with appropriate loaders. Adding more rules to laravel-mix
config seems to make no difference. All dependencies are up-to date and work well with vue-loader v.14.2.2
. Node.js version is 10.1.0
and npm is 6.1.0
.
Also here is my package.json:
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.18.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"cross-env": "^5.1.6",
"css-loader": "^0.28.11",
"laravel-mix": "2.1",
"lodash": "^4.17.10",
"node-sass": "^4.9.0",
"pug": "^2.0.3",
"pug-loader": "^2.4.0",
"pug-plain-loader": "^1.0.0",
"sass-loader": "^7.0.1",
"sass-resources-loader": "^1.3.3",
"vue": "^2.5.16",
"vue-html-loader": "^1.2.4",
"vue-loader": "^15.2.1",
"vue-style-loader": "^4.1.0"
},
"dependencies": {
"es6-promise": "^4.2.4",
"vue-multiselect": "^2.1.0",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
}
}
Here is resolve statement from WebpackConfig.js
buildResolving() {
this.webpackConfig.resolve = {
extensions: ['*', '.js', '.jsx', '.vue'],
alias: {
vue$: 'vue/dist/vue.common.js'
}
};
return this;
}
And here is all of my webpack.mix.js
mix.js('resources/assets/js/app.js', 'public/js')
.copy('resources/assets/fonts/', 'public/fonts/')
.webpackConfig({
plugins: [
new VueLoaderPlugin()
],
resolve: {
alias: {
'Global': path.resolve('resources/assets/sass')
}
}
})
I have it working fine. Here's a library project using laravel mix with Vue Loader 15 - https://github.com/niiknow/vue-datatables-net
I don't have a public Laravel project to demonstrate but here's my private project package.json
{
"private": true,
"scripts": {
"clean": "rm -rf ./public/js/parts/*",
"dev": "npm run development",
"development": "npm run clean && cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "npm run clean && cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "npm run clean && cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "npm run clean && cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"test": "npm run clean && cross-env NODE_ENV=test mocha-webpack --webpack-config=node_modules/laravel-mix/setup/webpack.config.js --require tests/Vue/setup.js tests/Vue/**/*.spec.js",
"watch-test": "npm run clean && cross-env NODE_ENV=test mocha-webpack --webpack-config=node_modules/laravel-mix/setup/webpack.config.js --watch --require tests/Vue/setup.js tests/Vue/**/*.spec.js",
"lint": "eslint --ext .js,.vue resources/js",
"lint-fix": "eslint --fix --ext .js,.vue resources/js",
"check-outdated": "npm outdated"
},
"devDependencies": {
"autotrack": "^2.4.1",
"axios": "^0.18.0",
"axios-jsonp": "^1.0.2",
"babel-core": "^6.26.3",
"babel-eslint": "^10.0.1",
"babel-loader": "^7.1.5",
"babel-plugin-transform-imports": "^1.5.1",
"babel-polyfill": "^6.26.0",
"babel-preset-vue-app": "^2.0.0",
"bootstrap": "^4.1.3",
"bootstrap-vue": "^2.0.0-rc.11",
"browser-sync": "^2.26.0",
"browser-sync-webpack-plugin": "^2.0.1",
"cross-env": "^5.1.6",
"datatables.net-bs4": "^1.10.19",
"datatables.net-buttons-bs4": "^1.5.4",
"datatables.net-fixedheader-bs4": "^3.1.5",
"datatables.net-responsive-bs4": "^2.2.3",
"eslint": "^5.9.0",
"eslint-config-prettier": "^3.3.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.1.0",
"eslint-plugin-vue": "^5.0.0-beta.4",
"inputmask": "^4.0.3",
"jQuery-QueryBuilder": "^2.5.2",
"jquery": "^3.3.1",
"laravel-mix": "^2.1.14",
"lodash": "^4.17.11",
"noty": "^3.2.0-beta",
"popper.js": "^1.14.5",
"sweetalert2": "^7.29.0",
"tinycolor2": "^1.4.1",
"vee-validate": "2.1.2",
"vform": "^1.0.0",
"vue": "^2.5.17",
"vue-authenticate": "^1.3.4",
"vue-axios": "^2.0.2",
"vue-datatables-net": "^1.0.1",
"vue-element-loading": "^1.0.5",
"vue-i18n": "^8.3.1",
"vue-loader": "^15.4.2",
"vue-router": "^3.0.1",
"vue-template-compiler": "^2.5.17",
"vue2-google-maps": "^0.10.2",
"vuedraggable": "^2.16.0",
"vuex": "^3.0.1",
"vuex-persistedstate": "^2.5.4",
"vuex-router-sync": "^5.0.0"
},
"dependencies": {},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 9"
],
"engines": {
"node": ">= 8.10.x",
"npm": ">= 5.6.0"
}
}
And here's my webpack.mix.js
const path = require('path');
const mix = require('laravel-mix');
const { VueLoaderPlugin } = require('vue-loader');
const source = 'resources';
const public = 'public';
mix.options({
processCssUrls: false,
uglify: {
uglifyOptions: {
compress: {
drop_console: true
}
}
}
});
mix.setPublicPath(path.normalize(public));
mix.webpackConfig({
externals: {
'jquery': 'jQuery'
},
output: { chunkFilename: 'js/parts/[name].js' },
module: {
rules: [
{
enforce: 'pre',
test: /\.(vue|js)$/,
exclude: /(node_modules|bower_components)/,
loader: 'eslint-loader',
options: {
fix: false,
cache: false,
formatter: require('eslint-friendly-formatter')
}
}
]
},
plugins: [
new VueLoaderPlugin()
],
devServer: { overlay: true },
devtool: 'source-map',
resolve: {
/* Path Shortcuts */
alias:{
/* root */
'~': path.resolve(__dirname, `${ source }/js`),
Components: path.resolve(__dirname, `${ source }/js/components`),
Layouts: path.resolve(__dirname, `${ source }/js/layouts`),
Pages: path.resolve(__dirname, `${ source }/js/pages`)
}
}
});
mix.js(`${ source }/js/myapp.js`, `${ public }/js`);
mix.sass(`${ source }/sass/myapp.scss`, `${ public }/css`, {
outputStyle: mix.inProduction() ? 'compact' : 'expanded'
});
mix.sourceMaps();
mix.browserSync({
proxy: 'yourproject.test',
host: 'yourproject.test',
files: [
`${ source }/views/**/*.php`,
`${ public }/js/**/*.js`,
`${ public }/css/**/*.css`
],
browser: 'firefox',
ghostMode: false,
open: 'external'
});
mix.extract([
'autotrack',
'axios',
'axios-jsonp',
'noty',
'popper.js',
'sweetalert2',
'tinycolor2',
'vee-validate',
'vform',
'vue',
'vue-authenticate',
'vue-axios',
'vue-element-loading',
'vue-i18n',
'vue-router',
'vue2-google-maps',
'vuedraggable',
'vuex',
'vuex-persistedstate',
'vuex-router-sync'
]);
if (mix.inProduction()) {
mix.version();
mix.disableNotifications();
}
And here's my .babelrc
{
"presets":
[
[
"env",
{
"targets": {
"browsers": ["last 2 versions"]
},
"debug": true,
"useBuiltIns": "entry"
}
]
],
"plugins": ["transform-runtime", "syntax-dynamic-import"]
}
Here's .eslint.js
module.exports = {
root: true,
env: {
browser: true,
},
plugins: ['vue'], // enable vue plugin
extends: ["plugin:vue/recommended", "prettier"], // activate vue related rules
parserOptions: {
"parser": "babel-eslint",
"ecmaVersion": 7,
"sourceType": "module",
"ecmaFeatures": {
"globalReturn": false,
"impliedStrict": false,
"jsx": false,
"experimentalObjectRestSpread": false,
"allowImportExportEverywhere": false
}
},
rules: {
// allow paren-less arrow functions
"arrow-parens": 0,
// allow async-await
"generator-star-spacing": 0,
// allow debugger during development
"no-debugger": process.env.NODE_ENV === 'production' ? 2 : 0,
"semi": [2, "never"],
"quotes": [2, "single"],
"vue/require-default-prop": 0,
"vue/require-prop-types": 0,
"vue/no-v-html": 0
}
};