This question will be a bit long, but I need to explain the context, so be patient, please.
I am working on an Reacj/Ruby application structured in the following way:
<my_app>
|
|_____be/
|
|_____fe/
| |
| |_____node_module/
| |_____public/
| | |_____index.html
| | |_____index.jsx
| | |_____index.test.js
| | |_____bundle.js
| |_____src/
| |_____app/
| | |_____app.jsx
| | |_____app.test.js
| | |_____app.css
| |_____contents/
| | |_____contents.jsx
| | |_____contents.test.js
| | |_____contents.css
| |_____footer/
| | |_____footer.jsx
| | |_____footer.test.js
| | |_____footer.css
| |_____header/
| | |_____header.jsx
| | |_____header.teste.js
| | |_____header.css
| |_____package.json
| |_____index.jsx
| |_____index.test.js
| |_____index.css
|_____config.ru
|_____Gemfile
|_____Gemfile.lock
|_____integrations.json
|_____package.json
|_____webpack.config.js
It is a mix of pure Ruby (no Rails, no Sinatra) and ReactJS, where app, contents, footer and reader are ReactJS components. The idea is separating completely the backend be from the frontend fe, orchestrated by webpack and Rack, where I am going to use fetch to grab dynamical data from tye backend.
The application, after bundled with Webpack, will be run by Rack. The Rack::Static middleware will deal with serving the static assets built by npm run build and a Ruby gem I created will redirect the calls made by de frontend to a set of POROs (Plain Old Ruby Objects) which will provide de dynamic data. It is a small framework, as you may see. A concept I am trying to prove.
When it comes to fe, inside it everything is fine. When I enter its directoty and do npm test all tests run fine, and when I run npm start it runs fine too.
To make things simple in this test, all the ReactJS components do is write a single word. Like this:
app.jsx
import React from 'react';
import './app.css';
import Header from '../header/header.jsx';
import Contents from '../contents/contents.jsx';
import Footer from '../footer/footer.jsx';
export default class App extends React.Component {
render() {
return (
<div className="app">
<Header />
<Contents />
<Footer />
</div>
);
}
}
And this:
header.jsx
import React from 'react';
import './header.css';
export default class Header extends React.Component {
render() {
return (
<p>Header</p>
);
}
}
This way, when I run npm start inside fe, all I see in my browser (at http://localhost:3000) is
Header
Contents
Footer
Well, everything fine until this point. But I need to bundle the frontend app with Webpack. This is my configuration:
webpack.config.js
var path = require('path');
module.exports = {
entry: path.resolve(__dirname, 'fe/src/') + '/index.js',
output: {
path: path.resolve(__dirname,'fe/public/'),
filename: 'bundle.js'
},
devServer: {
inline: true,
contentBase: './public',
port: 3333
},
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
}]
}
}
As you may see, I am creating bundle.js at fe/public. And my Rack::Static is configured to serve the index.html inside fe/public to all static requests, while my gem deals with the dynamical ones.
It happens that, although all modules are correctly installed and everything is bundled correctly, I see nothing when I run my app with rackup. No error, no problem... and no words! Just a blank browser screen.
What exactly am I missing?
EDIT:
package.json
{
"name": "emerald_application",
"title": "Emerald Framework Application",
"version": "0.1.0",
"private": true,
"dependencies": {
"bootstrap": "^3.3.7",
"fb": "^1.1.1",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-router": "^4.0.0"
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"react-scripts": "0.9.5",
"webpack": "^2.5.1",
"webpack-dev-server": "^2.4.5"
},
"scripts": {
"start": "npm run serve | npm run dev",
"dev": "webpack-dev-server --progress --colors --port 8090"
}
}
No, I haven't used create-react-app. But this is not a problem, because the fe part is running fine, i.e., the ReactJS part runs fine by itself and I know enough about ReactJS apps to create them even without create-react-app, specially one so small.
I solved the issue by manking some changes to the code.
First of all, I edited the webpack.config.js.
webpack.config.js
var path = require('path');
module.exports = {
entry: path.resolve(__dirname, 'fe/src/') + '/index.jsx',
output: {
path: path.resolve(__dirname, 'public'), // <<== THIS
filename: 'bundle.js'
},
devServer: {
inline: true,
contentBase: './app',
port: 3333
},
module: {
loaders: [{
test: /\.jsx?$/,
exclude: [ "node_modules" ],
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
}]
}
}
As you may see, this is going to make Webpack put the bundle.js file in a public directory at the root of my app. After that I created an index.html file inside the same public directory. Pointing to an index.html inside fe/src would create a lot of trouble with the paths to images and other resources, which now will be put at public/resources where it will be easier to refer to them at the pages created. My index.html file now reads:
index.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>
After doing this, the app wasn't still running. Webpack couldn't find the node modules installed. They were inside the fe dir, then I just created a symlink with
$ ln -sf fe/node_modules
and then webpack run perfectly well and created the bundle.
This was my main goal, isolate the frontend completely inside the fe directory and be able at the same time to run this application from outside this dir, where I may run the complete application (backend and frontend) with a single command and under a single process. This will make the deploy easier at Heroku and other similar services.
I thank all those who took time to help me with this. This was the last step to have my web development framework running. Now it is just a matter of improving it even more.
Related
I'm trying to get Vue.js 2.0 typings working with TypeScript in Visual Studio. Previously, I had used these typings from DefinitelyTyped, but they are for Vue.js 1.0 and thus don't match up. However, they did work just fine and let me work with the Vue type.
I've since transitioned to using the typing files that come with Vue.js releases (here). I have included them in my project in my ~/Scripts/typings/vue folder, but my project does not understand them.
I've gathered that these typing files are meant to be used via import/export possibly? There are no other typing files I am using that work this way, so I am not sure how to correctly implement the typings such that they are available globally to my project.
I have a sample solution that shows an example of what I've tried - download here from my github repo.
Here's the structure of my Scripts folder:
_references.d.ts contents
/// <reference path="typings/vue/index.d.ts" />
vue_test.ts contents
namespace Test
{
export class MyClass
{
public initialize()
{
var component = this.getComponent();
}
private getComponent(): Vue.Component
{
return Vue.component("test", {
template: "<div></div>",
props: ["test"],
methods: {
onClick: () =>
{
}
}
});
}
}
}
What I would expect is that I would have access to the Vue.Component namespace and other namespaces that are declared in typings/vue/index.d.ts, but this does not seem to be the case.
I did attempt to import the exported class into global, like this:
import * as _Vue from "./index";
declare global
{
export class Vue extends _Vue
{
}
}
However, this only allows me to access the root Vue class, and thus I cannot do things like specify Vue.Component as a type, or any other namespace beyond Vue.
Other information:
Visual Studio 2015
Vue.js version 2.2.1
TypeScript version 2.1
UPDATE after suggestions from #unional
Here is my new folder structure:
No more _references.d.ts, using tsconfig.json instead. The tsconfig.json file contains this:
{
"compilerOptions": {
"sourceMap": true
},
"include": [
"../../**/*.ts"
]
}
The above imports all .ts files in the project. The ~/Scripts/typings/custom-typings/vue.d.ts file contains the following:
export * from "vue"
export as namespace Vue
Visual Studio tells me Cannot find module 'vue', so my typings are still not functional, although the tsconfig.json file works (I added the jQuery typing to verify that).
Here is a link to the updated solution showing the new problems: [link]
With NPM
Drop down to the command line in your app's root directory to use NPM and the TypeScript command line interface.
If you do not already have a package.json file, then first run npm init.
Then to install vue.js, run npm install --save vue.
To install its types run npm install --save-dev #types/vue.
If you also lack a tsconfig.json file, then run tsc --init.
At that point, you will be able to build by running tsc.
Without NPM
Not using NPM is unconventional and will require a lot of manual work. Here is one of those manual approaches.
Download VueJS 2.1.1 from the GitHub repo. After extracting the archive,
Put the contents of dist into Scripts/vuejs directory,
Put the contents of typings into typings/vuejs directory,
Add a tsconfig.json file to your project's root that his this content.
tsconfig.json
{
"compilerOptions": {
// ....... other properties omitted
"typeRoots": [
"./typings/"
],
"target": "es5",
"lib": ["es2015", "dom", "es2015.promise" ]
}
}
Then, at the top of the file that will be using Vue, add a relative import statement.
import * as Vue from "../typings/vuejs";
interface MyComponent extends Vue {
message: string
onClick (): void
}
export default {
template: '<button #click="onClick">Click!</button>',
data: function () {
return {
message: 'Hello!'
}
},
methods: {
onClick: function () {
window.alert(this.message)
}
}
}
Example
Here is an updated version of your WebApplication1 example.
https://github.com/bigfont/StackOverflow/tree/master/TypeScriptVueJsTypes
See also:
https://v2.vuejs.org/v2/guide/typescript.html
https://github.com/vuejs/vue
I was able to use information from #unional's comment, but with a slight change:
I added this to my custom-vue.d.ts file:
import * as _Vue from 'vue';
export as namespace Vue;
export = _Vue;
Additionally, I had to create a package.json file with the following:
{
"dependencies": {
"vue": "^2.2.1"
}
}
Finally, I needed to add a node_modules folder at the same scope as my tsconfig.json file. It has the following:
+-- node_modules
| +-- vue
| | +-- package.json
| | +-- types
| | | +-- index.d.ts
| | | +-- options.d.ts
| | | +-- plugin.d.ts
| | | +-- vnode.d.ts
| | | +-- vue.d.ts
package.json simple contains:
{
"typings": "types/index.d.ts"
}
And things are now WORKING
Edit
Alternatively, I discovered I could avoid the whole node_modules thing by setting tsconfig.json's property for moduleResolution to Classic. After doing that, I changed my custom-vue.d.ts import to look like this:
import * as _Vue from "../vue/index";
Since the error is at compile time, No big problem in it. you can use this plugin to for faster development from here
Also, the code should be as
import Vue from 'vue'
import Component from 'vue-class-component'
// The #Component decorator indicates the class is a Vue component
#Component({
template: ''
})
export default class MyComponent extends Vue {
}
and so on. You can still use the vuejs inside your cshtml files.
I am working with Pug and I wanted to create some mixins to make some reusable components across whole project. I wanted to create some files just to make mixins separated and categorised. The problem occurs when I want to include file with mixins into my main file. For example:
body
block content
include ./components/mixins/_mixins.pug
+user_avatar('', '#', 'Daniel')
This does not work (when I want to include mixins from separate file). I got this error: jade_mixins.user_avatar is not a function
But when I include mixin in the file it works:
body
block content
mixin user_avatar(avatar_url, profile_url, name)
.user(class='4u 6u(small) 12u(xsmall)')
a(href=profile_url)
.user-avatar-thumbnail.is-active(style="background-image: url('" + avatar_url + "')")
if name
span.user-name=name
+user_avatar('', '#', 'Daniel')
Any clue what to do to fix it? And yeah, the path is correct. To compile pug I use the laravel-elixir-jade package for laravel's elixir.
I've tried to reproduce your issue, but on my machine, it seems to work just fine. I'm listing the setup I made for this below, maybe you can find the point where yours deviates from this one.
My directory structure:
|- html/
|--- template.html (generated after running gulp)
|- node_modules/
|- views/
|--- mixins/
|----- util.pug
|--- template.pug
|- gulpfile.js
|- package.json
My package.json:
{
"name": "test",
"version": "1.0.0",
"main": "gulpfile.js",
"license": "MIT",
"dependencies": {
"gulp": "^3.9.1",
"laravel-elixir": "^6.0.0-15",
"laravel-elixir-pug": "^1.3.2",
"pug": "^2.0.0-beta6"
}
}
My template.pug:
body
block content
include mixins/util
+test()
The util.pug file:
mixin test()
p Test
And the gulpfile.js:
var elixir = require('laravel-elixir');
require('laravel-elixir-pug');
elixir(function (mix) {
mix
.pug({
blade: false,
src: './views',
search: '**/*.pug',
pugExtension: '.pug',
dest: './html'
});
});
After running gulp in the root directory, this produces the following template.html, as expected:
<body>
<p>Test</p>
</body>
Still trying to master NPM and hit some roadblocks.
My slick-carousel works great when I use the CDN process. But I'm doing everything in NPM so figured I should do the same with this plug-in, but can't seem to get it off the ground.
Ran the install:
npm install slick-carousel --save
Which adds to my package.json file:
"devDependencies": {
"copy-webpack-plugin": "^3.0.1",
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0",
"gh-pages": "^0.11.0",
"html-webpack-plugin": "^2.21.0",
"img-loader": "^1.3.1",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^1.13.1"
},
"dependencies": {
"font-awesome-webpack": "0.0.4",
"jquery": "^3.0.0",
"slick-carousel": "^1.6.0"
}
I'm smart enough to know that I need to require the file in my index.js file:
var $ = require('jquery');
require("../css/style.css");
require("font-awesome-webpack");
require("slick-carousel");
I can see that I now have all the jQuery for slick-carousel, but none of the css.
Now I figure I should require the two .css files living in the node_modules folder:
require("slick-carousel/slick/slick.css");
require("slick-carousel/slick/slick-theme.css");
And this is where it all breaks. The slick.css file loads and the basic slick-carousel is now working in my html output. But the slick-theme file breaks everything by pushing this error:
./~/slick-carousel/slick/ajax-loader.gif
Module parse failed: /Users/ryanbuchholtz/Documents/thinkful/haventower/node_modules/slick-carousel/slick/ajax-loader.gif Unexpected character '' (1:7)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected character '' (1:7)
This makes me think something is broken in my webpack.config.js:
var path = require('path');
var packageData = require('./package.json');
var filename = [packageData.name, packageData.version, 'js'];
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var CopyWebpackPlugin = require('copy-webpack-plugin');
var plugins = [
new HtmlWebpackPlugin({
inject: 'head',
template: 'index.html',
minify: {
"collapseWhitespace": true,
"removeComments": true,
"removeRedundantAttributes": true,
"removeScriptTypeAttributes": true,
"removeStyleLinkTypeAttributes": true
}
}),
new ExtractTextPlugin('style.css')
];
module.exports = {
entry: {
main: [
path.resolve(__dirname, packageData.main)
]
},
output: {
path: path.resolve(__dirname, 'build'),
filename: filename.join('.'),
},
devtool: 'source-map',
plugins: plugins,
module: {
loaders: [
{
test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader", "file-loader")
},
{ test: /\.(jpe?g|png|gif|svg)$/, loader: "file-loader"
},
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff"
},
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader"
}
]
}
};
I could really use some assistance in the best way to use slick-carousel while building in NPM and with webpack. So many moving pieces and, when I kinda think I get it, this comes along and I spend 7 hours trying to fix it before asking for help.
Any help is deeply appreciated.
I had the same issue, but I didn't want to change slick-carousel in my project, so one month late but here is how I solved it:
First install Webpack image-loader:
$ npm install image-webpack-loader --save-dev
Then change these lines (in your webpack configuration):
loaders: [{
test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader", "file-loader")
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'file?hash=sha512&digest=hex&name=[hash].[ext]',
'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'
]
},
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff" },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader"
}]
This will change file-loader (what you are using for loading images) for image-loader, it will know how to compile .gif files and other formats.
For aditional information about this, you can check the github page
Also, if you are using ReactJS, don't use slick-carousel directly, because it uses direct DOM manipulation thanks to JQuery dependency, right now I'm using react-slick is very stable and has cool options like settings based on responsive layout custom prev and next arrows and more.
I hope it help you
require("slick-carousel/slick/slick.css");
require("slick-carousel/slick/slick-theme.css");
From what I understand you do not need both of these - only one.
Slick-theme is the default CSS, while Slick you integrate.
I could be wrong (I'm really new to development) but I've had no problems with the initial configuration!
I am trying to set up Browserify with Elixir and Browserify Shim on Laravel 5.2 to use Gulp with my JavaScript files, but I didn't have much luck so far. This should be pretty straightforward to do, but it isn't.
Here is my package.json
{
"private": true,
"devDependencies": {
"gulp": "^3.8.8"
},
"dependencies": {
"bootstrap-sass": "^3.0.0",
"browserify-shim": "^3.8.12",
"jquery": "^2.2.0",
"jquery-ui": "^1.10.5",
"laravel-elixir": "^4.0.0"
},
"browser": {
"app": "./resources/assets/js/app.js",
"utils": "./resources/assets/js/utils.js",
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"browserify-shim": {
"app": {
"depends": [
"jquery:$",
"utils:Utils"
]
},
"utils": {
"depends": [
"jquery:$"
]
},
}
}
gulpfile.js
var elixir = require('laravel-elixir');
elixir(function (mix) {
mix.browserify('main.js', './public/js/bundle.js');
});
Entry script main.js looks like this:
var $ = require('jquery');
var Utils = require('utils');
var App = require('app');
app.js
var App = {
init: function(){
console.log(Utils);
Utils.doSomething();
}
//other methods
};
In short: Utils depends on $, and App depends on both $ and Utils.
When I hit gulp from terminal, bundle.js is correctly created. All scripts are wrapped up in Browserify code (as expected). Each script has all included dependencies, like I configured in package.json so this part looks good as well.
The problem is that all my included dependencies are empty objects. For example, Utils in app.js is empty, and I get an error when I try to call its method "doSomething". Console log prints out an empty object "{}" instead of real object. The only correctly included script is jQuery and it's not an empty object.
What could be wrong here? Do I need to make some changes in my JS files or in configuration to make this work? It looks like I'm pretty close to the solution, but it still does not work and I can't use it at all.
It is the easiest solution to directly use 'exports' from browserify-shim property:
"browserify-shim": {
"app": {
"exports": "App",
"depends": [
"jquery:$",
"utils:Utils"
]
},
"utils": {
"exports": "Utils",
"depends": [
"jquery:$"
]
},
}
Take a look at this repo which I believe shows the fixed version of your app. The issue is that your app.js and utils.js modules aren't exporting anything to their respective require calls. One option is to add a line like:
module.exports = App;
to the bottom of your app.js file, and the equivalent to the bottom of your utils.js file. You'll see if you test the repo that badapp doesn't have this line and produces the exact behavior you're describing.
See this answer for an explanation of the issue.
I'm using this tutorial to setup a React.js project with webpack. The webpack.config.js below is almost an exact copy (except that I'm using an app and 'dist' folder), and I am also adding d3.js as an external. Because React is added as an external it lets me do require('react') in any of my app files without including it in the bundle. I wish to do the same with d3.js and have installed it as a node_module, and listed it in the externals area of my webpack config, but when I do require('d3') i get an error message that it's not available.
How can I use d3 (or jQuery for that matter) as an external if I have it installed as a node_module?
this is my project setup
/app
/dist
/node_modules
package.json
webpack.config.js
module.exports = {
entry: './app/index.jsx',
output: {
path: './dist',
filename: 'bundle.js', //this is the default name, so you can skip it
//at this directory our bundle file will be available
//make sure port 8090 is used when launching webpack-dev-server
publicPath: 'http://localhost:8090/assets'
},
module: {
loaders: [
{
//tell webpack to use jsx-loader for all *.jsx files
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony'
}
]
},
externals: {
//don't bundle the 'react' npm package with our bundle.js
//but get it from a global 'React' variable
'react': 'React',
'd3': 'd3'
},
resolve: {
modulesDirectories: ['app', 'node_modules'],
extensions: ['', '.js', '.jsx']
}
}
I know this question has been open a while, but hopefully this answer is still useful!
If you have installed d3 (or jQuery) as a node_module, you can use the webpack ProvidePlugin to tie an arbitrary key to a module.
The key will be then be available to require anywhere in your webpack app.
E.g. webpack.config.js
{
...lots of webpack config here...
...
plugins: [
new webpack.ProvidePlugin({
d3: 'd3',
$: 'jquery'
})
]
...
}
Then in my-file.js
var d3 = require('d3')
Hope that helps!