Vue component not showing - laravel-5.3

I followed the series codetube "youtube clone" and I did everything like the Alex but the Vue component not working. I am not working on localhost but on server. I would be very glad for any suggestions.
My app.js
require('./bootstrap');
Vue.component('videoup', require('./components/VideoUpload.vue'));
const app = new Vue({
el: '#app'
});
My VideoUpload.vue file:
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Upload</div>
<div class="panel-body">
...
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
}
}
</script>
My blade file:
#extends('layouts.app')
#section('content')
<videoup></videoup>
#endsection
My app.blade file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<!-- <link href="/css/app.css" rel="stylesheet">-->
<link rel="stylesheet" href="/css/app.css">
<!-- Scripts -->
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
]); ?>
</script>
</head>
<body>
<div id="app">
#include('layouts.partials._navigation')
#yield('content')
</div>
<script src="/js/app.js"></script>
</body>
</html>
My gulfpile.js:
const elixir = require('laravel-elixir');
require('laravel-elixir-vue-2');
require('laravel-elixir-webpack-official');
elixir((mix) => {
mix.sass('app.scss')
.webpack('app.js');
});
My webpack.config.js:
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
// vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
devtool: '#eval-source-map'
};
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map',
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
};

It's difficult to debug your setup because I have no idea what tutorial you followed, how you are bundling your code (webpack or browserify) or what build tools you are using (gulp, elixir etc), but I think the most important thing is to understand how Vue works, and then you will be able to better understand how to solve this yourself.
Firstly, vue has two builds - a standalone build and a runtime-only build. The difference between these is that the standalone build includes a template compiler and the runtime-only build does not.
Render Functions
Vue compiles templates in to render functions to work (which are just javascript functions), it doesn't use HTML at all, so if you haven't written a render function or you haven't pre-compiled your components (using .vue files and a bundler like browserify or webpack) then you must use the standalone build; and this includes the base component itself, so the important thing to know is:
If you are trying to use a component inside anything other than a .vue file you need to use the standalone build.
because you need the compiler to turn the HTML into a render function.
So, looking at your code, you are trying to use your component inside a .blade.php file, which isn't a single file component so you will need the standalone build in your project.
When using npm, vue imports the runtime-only build by default:
// ES6
import `Vue` from `vue` // this imports the runtime-only build
// ES5
var Vue = require('vue'); // this requires the runtime-only build
But you need to make sure you are using the standalone build, and how you do this depends on whether you use webpack or browserify. If you are using webpack, you need to add the following to your webpack config:
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js'
}
}
If you are using browserify you will need to add the following to your package.json:
"browser": {
"vue": "vue/dist/vue.common"
},
And also make sure that resources/assets/views/layouts/app.blade.php wraps everything in a div with the id app:
...
<body>
<div id="app">
...
</div>
</body>
...
Update
Based on your webpack config it looks like your issue is here:
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
This says you are compiling main.js in the src folder and outputting it to the dist folder as build.js.
Laravel uses a different structure, so you will need to change this to:
entry: './resources/assets/js/app.js',
output: {
path: path.resolve(__dirname, './public/js'),
publicPath: '/public/',
filename: 'app.js'
},
This now says, compile resources/assets/js/app.js and output the file to public/js/app.js. I don't use webpack myself so that may need a little tweaking, but that should get your project up and running.

I had the same issue. the following solved it for me..
I changed:
require('./components/mycomponent.vue')
to:
import MyComponent from "./components/mycomponent.vue";

Related

Load Vue 3 Component inside mounted div and pass PHP data

I'm currently working on a new project where I have to integrate Vue 3 in a large Symfony/Drupal project.
The project already contains a lot of PHP code and actually I don't want to refactor too much to begin with.
Well I tried setting up a very small piece of Vue code to see how I could start working on the rest of the code. Actually I just want some PHP code to be transferred from index.html.twig to the sidebar.vue file. I also work with Webpack Encore by the way from Symfony. I read that I could use Vue components to achieve this but my components are not loaded inside my <div id="app"></div>. Or atleast not how I want them to load.
webpack.config.js (Webpack Encore)
var Encore = require('#symfony/webpack-encore');
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
.setOutputPath('webroot/public/build/')
.setPublicPath('/public/build')
.addEntry('main', './vue/src/main.js')
.splitEntryChunks()
.enableSingleRuntimeChunk()
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
.enableVersioning(Encore.isProduction())
.configureBabelPresetEnv((config) => {
config.useBuiltIns = 'usage';
config.corejs = 3;
})
.enableSassLoader()
.enablePostCssLoader()
// enables Vue
.enableVueLoader(() => {}, {
version: 3,
runtimeCompilerBuild: false,
});
;
module.exports = Encore.getWebpackConfig();
main.js
import { createApp } from 'vue';
import Sidebar from './components/sidebar';
const app = createApp({})
app.component('sidebar', Sidebar);
app.mount("#app");
sidebar.vue
<template>
<h1>Sidebar</h1>
</template>
<script>
export default {
name: 'Sidebar',
};
</script>
<style lang="scss" module>
</style>
index.html.twig
<div id="app"> <!-- The vue #app is loaded -->
<sidebar></sidebar> <!-- This is not loading -->
</div>
<!-- If it's loading I want to setup something like this -->
<div id="app"> <!-- The vue #app is loaded -->
<sidebar :item="{{ $item }}"></sidebar> <!-- This is not loading -->
</div>
{{ encore_entry_script_tags('main') }}
So how can I make <sidebar></sidebar> to load inside the HTML/Twig file? In the next step I would like to pass some PHP data on the <sidebar> component so I can read it inside the sidebar.vue file. Something like: <sidebar :item="{{ $item }}"></sidebar>
I'm not entirely sure if this is possible with my current setup but I would love to see it work like this or in a similar way.
It seems like I'll have to use the runtimeCompilerBuild. That solves the problem. When false Vue can only be used with single file components which performs better but is less suitable for my application at the moment.
.enableVueLoader(() => {}, {
version: 3,
runtimeCompilerBuild: true,
});
Instead of
runtimeCompilerBuild: false;
In your main.js do :
app.mount("sidebar");
instead of
app.mount("#app");

Delayed loading of css on page refresh (Webpack)

I have splitted webpack configurations, common, development and production configs. I load also jQuery via webpack. The problem is that, on page refresh, there is short delay for about 200-300ms before css is loaded, so my page is firstly shown without it, and then reloads with css. What could be the problem?
In common, under plugins, I have:
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
In development config I have:
{
test: /\.scss$|\.css$/,
use: [
{
loader: "style-loader",
options: {sourceMap: true}
},
{
loader: "css-loader",
options: {sourceMap: true}
},
{
loader: "sass-loader",
options: {sourceMap: true}
}
]
},
and for production mode:
optimization: {
minimizer: [
new UglifyJSPlugin({
sourceMap: true,
uglifyOptions: {
mangle: false,
compress: {
inline: false
}
}
}),
new OptimizeCssAssetsPlugin({
cssProcessor: require('cssnano'),
cssProcessorOptions: {parser: _safe, discardComments: {removeAll: true}},
canPrint: true
})
]
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
}
]
}
EDIT
Here is compiled html file:
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=UTF-8>
<meta name=viewport content="width=device-width">
<meta http-equiv=X-UA-Compatible content="ie=edge">
<link rel="shortcut icon" href="favicon.png">
</head>
<body>
<div id=app></div>
<script type="text/javascript" src="main.bundle.js?32313079e3d03749d814"></script>
</body>
</html>
Maybe it is too late to answer this question, however, that is not related to Webpack. You have attached your bundle at the end of the page. Therefore before loading the bundle the page content comes up and after that bundles loaded the style. Therefore until it loads the completely there is a little time that takes time for the browser to run the bundle and attach the style. It can be fixed by putting the bundle in the <head> tag. You may need to run your jquery codes inside $(document).ready() function by passing a callback as an argument. Pay attention that it can affect the load time of your page as well.
Another solution can be configuring Webpack to load the styles first and then your js codes.

VueJS 2 + ASP.NET MVC 5

I'm very new with VueJS.
I have to build a single page application inside a ASP.NET MVC5.
I follow this tutorial and works very well -> TUTORIAL
But when i create a .vue page to test VueJS2 Routes, the browser does not understand "Import", i read that i have to use a transpiler like Babel, someone know how i solve it?
App.VUE
<template>
<div id="app">
{{msg}}
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
App.JS
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
router,
render: h => h(App),
data: {
message: 'Hello Vue! in About Page'
}
});
_Layout.cshtml
<div class="container-fluid">
#RenderBody()
<div id="app">
{ { message } }
</div>
</div>
<script src="~/Scripts/essential/jquery-3.1.1.min.js"></script>
<script src="~/Scripts/essential/bootstrap.min.js"></script>
<script src="~/Scripts/essential/inspinia.js"></script>
<script src="~/Scripts/essential/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/2.0.1/vue-router.js"></script>
<script src="~/Scripts/app.js"></script>
<script src="~/Scripts/plugin/metisMenu/jquery.metisMenu.js"></script>
<script src="~/Scripts/plugin/pace/pace.min.js"></script>
<script src="~/Scripts/plugin/slimscroll/jquery.slimscroll.min.js"></script>
Thanks a lot!!
Welcome to Vue.js development! Yes, you are correct, you need something to translate the import statements into JavaScript that the browsers can handle. The most popular tools are webpack and browserify.
You are also using a .vue file, which needs to be converted (with vue-loader) before the browser can pick it up. I am going to lay out how to do this, and set up webpack, which involves a few steps. First, the HTML we're working with looks something like this:
<html>
<head>
</head>
<body>
<div class="container-fluid">
<div id="app">
{ { message } }
</div>
</div>
<script src="./dist.js"></script>
</body>
</html>
Our goal is to use webpack to bundle / compile App.vue and app.js into dist.js. Here is a webpack.config.js file that can help us do that:
module.exports = {
entry: './app.js',
output: {
filename: 'dist.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
}
}
This configuration says, "start in app.js, replace import statements as we come across them, and bundle it into a dist.js file. When webpack sees a .vue file, use the vue-loader module to add it to dist.js."
Now we need to install the tools / libraries that can make this happen. I recommend using npm, which comes with Node.js. Once you have npm installed, you can put this package.json file in your directory:
{
"name": "getting-started",
"version": "1.0.0",
"scripts": {
"build": "webpack"
},
"dependencies": {
"css-loader": "^0.28.7",
"vue": "^2.4.2",
"vue-loader": "^13.0.4",
"vue-resource": "^1.3.3",
"vue-router": "^2.7.0",
"vue-template-compiler": "^2.4.2",
"webpack": "^3.5.5"
}
}
And do the following:
Run npm install to get all of the packages.
Run npm run-script build to generate your dist.js file via webpack.
Note in the example for this question, router is undefined in app.js, but here is a fixed-up file:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
var router = new VueRouter();
new Vue({
el: '#app',
router,
render: h => h(App),
data: {
message: 'Hello Vue! in About Page'
}
});
That should be it! Let me know if you have any questions.

How to stop FOUC when using css loaded by webpack

I am getting FOUC when loading css inside of my entry point when using webpack. If I remove my css from being loaded by webpack and just include it in my html file as a normal link then the problem with FOUC goes away.
Note: This not just with bootstrap framework, I have tested with
Foundation and Materialize with the same results
The code posted below is just a test example of my problem using Bootstrap.
Html code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Navbar example</h1>
</div>
</div> <!-- /container -->
<script src="build/bundle.js"></script>
</body>
</html>
bootstrap.js main entry point
import "../node_modules/bootstrap/dist/css/bootstrap.css";
import bootstrap from 'bootstrap'
$(document).ready(function () {
console.log('bootstrap loaded')
});
webpack.config.js
var path = require('path');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const webpack = require("webpack");
module.exports = {
entry: './src/bootstrap.js',
output: {
path: path.join(__dirname, 'build'),
filename: 'bundle.js'
},
resolve: {
extensions: ['', '.js']
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
'window.jQuery': 'jquery'
})
],
devtool: 'inline-source-map',
module: {
resolve: {
modulesDirectories: ['node_modules']
},
loaders: [
{
test: path.join(__dirname, 'src'),
loader: 'babel-loader',
query: {
presets: ['es2015']
}
},
{ test: /\.css?$/, loader: 'style!css'},
{ test: /\.html$/, loader: 'html' },
{ test: /\.(png|gif|jpg)$/, loader: 'url', query: { limit: 8192 } },
{ test: /\.woff2(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url', query: { limit: 10000, mimetype: 'application/font-woff2' } },
{ test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url', query: { limit: 10000, mimetype: 'application/font-woff' } },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file' },
]
}
};
ExtractTextWebpackPlugin will allow you to output your CSS as a separate file rather than having it embedded in your JS bundle. You can then include this file in your HTML, which as you said, prevents the flash of unstyled content.
I'd recommend only using this in production environments, as it stops hot-loading from working and makes your compile take longer. I have my webpack.config.js set up to only apply the plugin when process.env.NODE_ENV === "production"; you still get the FOUC when you're doing a development build/running the dev server, but I feel like this is a fair trade off.
For more information on how to set this up, take a look at SurviveJS's guide.
Update: As noted in the comments, ExtractTextWebpackPlugin has now been superceded by mini-css-extract-plugin - you should use that instead.
A bit late to the party, but here's how I do it.
While I recognize the merits of extract-text-plugin, it's plagued by a rebuild bug that messes up css order, and is a pain to set up. And setting timeouts in js is not something anyone should be doing (it's ugly and is not guaranteed 100% to prevent fouc)...
So my index.html is:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style>
#app { display: none }
</style>
<title></title>
</head>
<body>
<div id="app"></div>
<script src="scripts/bundle.js"></script>
</body>
</html>
Then, in client.js at the very end I add:
include "./unhide.css";
...and unhide.css contains a single line:
#app { display: block }
Voila, you see nothing until the whole app is loaded.
It's janky, but I wrap ReactDom.render() in a setTimeout() in my root index.js file.
setTimeout(ReactDOM.render(...), 0)

Combine and minify all bower libraries with gruntjs

Is there a way to combine and minify all bower installed libraries into 1 file automatically?
First I tried the most basic approach: combine all .js files from all subdirectories:
uglify: {
options: {compress: true},
my_target: { files: {
'vendor.js': ['bower_components/**/*.js'],
} } }
But this is obviously a bad approach. It also doesn't work because of too many errors.
I manually deleted all the files and kept only 1 (main) file that each library has, and it worked.
Is there a way to do this all automatically?
Also, is it advisable to do it? (i.e. combine all vendor libraries into 1 file)
I recommend the combination of 2 nice grunt libraries, Wiredep and Usemin:
Wiredep: Load all dependencies of bower identified in bower.json inside your html automatically
Usemin: Detect all src inside two comments tags and all that source are minified and concatenated in dist folder, below are a little example of a grunt files using this packages, is based on the generator of angular to yeoman this is only a brief of that grunt
Grunt
wiredep: {
options: {
cwd: 'appFolder'
},
app: {
src: ['htmlCollections'],
ignorePath: /\.\.\//
}
},
useminPrepare: {
html: 'htmlCollections',
options: {
dest: 'distributionFolder',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
},
usemin: {
html: ['distributionFolder+HtmlFiles'],
css: ['distributionFolder+cssFiles'],
js: ['distributionFolder+javascriptFiles']
}
HTML
<!doctype html>
<html lang="en" ng-app="MobileDev" id="ng-app">
<head>
<!-- build:css(app) styles/vendor.css -->
<!-- bower:css -->
//This gonna be generated for the grunt by dependencies in bower
<!-- endbower -->
<!-- endbuild -->
<!-- build:css(.tmp) styles/main.css -->
//All the script inside this gonna be concatened and minified in
//the dist folder by the name of main.css
<link type="text/css" rel="stylesheet" href="styles/app.css"/>
<!-- endbuild -->
</head>
<body>
<!-- build:js(app) scripts/vendor.js -->
<!-- bower:js -->
//This gonna be generated for the grunt by dependencies in bower
//And in distribution all bower components added gonna be minified by usemin in
//vendor.js
<!-- endbower -->
<!-- endbuild -->
<!-- build:js({.tmp,app}) scripts/scripts.js -->
//All the script inside this gonna be concatened and minified in the dist
//folder by the name of scripts.js
<script type="text/javascript" src="scripts/numero1"></script>
<script type="text/javascript" src="scripts/numero2"></script>
<!-- endbuild -->
</body>
Just needed wiredep
uglify: {
options: { compress: true },
my_target: {
files: { 'public/vendor.js': require('wiredep')().js
} } },
cssmin: {
minify: {
files: { 'public/vendor.css': require('wiredep')().css
} } },

Resources