Rails 5.1 api webpacker and vuejs - ruby-on-rails

I'm trying to create a Rails API and a client in VueJs using webpacker on Cloud9.
After a standard installation : npm install -g yarn && rails _5.1.4_ new . --api --webpack=vue
I'm using Foreman to launch rails and webpack, here is the file.
# Procfile.dev
web: bundle exec rails s -p $PORT -b $IP
webpacker: ./bin/webpack-dev-server --inline true --hot true --public $C9_HOSTNAME
I changed the development part of config/webpacker.yml to this :
development:
<<: *default
compile: true
# Reference: https://webpack.js.org/configuration/dev-server/
dev_server:
https: false
host: localhost
port: 8081
When launching foreman start the webpack creates public/packs/manifest.json containing the follow object.
{
"application.js": "/packs/application-d2ce57fea2210882a7d4.js",
"hello_vue.css": "/packs/hello_vue-9cb5a7334a6577c3422968b9b9970b2f.css",
"hello_vue.js": "/packs/hello_vue-d8d50a7562d6abcbea06.js"
}
I created a public/index.html file containing the following
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="packs/hello_vue-9cb5a7334a6577c3422968b9b9970b2f.css" />
</head>
<body>
<script type="text/javascript" src="packs/application-d2ce57fea2210882a7d4.js"></script>
<script type="text/javascript" src="packs/hello_vue-bd484161b1956b3a536b.js"></script>
</body>
</html>
Now when I go to the URL I have the Hello World from Webpacker in my JavaScript console and the Hello Vue! in the browser.
My question is : Is it possible to use this generated manifest.json to automatically launch the good files (js, css) and how ?

There is a plugin called html-webpack-plugin that can create the index.html file with all the good css and js links.
I just had to npm install html-webpack-plugin --save-dev and then modify my config/webpack/development.js like this :
const environment = require('./environment')
const HtmlWebpackPlugin = require('html-webpack-plugin')
environment.plugins.prepend('HtmlWebpackPlugin', new HtmlWebpackPlugin({
title: 'My Vuejs App',
inject: true
}))
module.exports = environment.toWebpackConfig()

Related

How to connect to a docker container from web?

I am working on a new project where I need to connect to a docker container from web?
By connect I mean I will create a shell in the website and tat shell will be able to connect to the running container.
I am not able to figure out how to proceed with the project.
Can anyone help me out?
From what I know there is no out of the box solution, you should make your own api executing command on your container running docker exec <id> <command> and returning the output, mind escape the command.
However you should know that letting a user run commands inside a docker is dangerous as it could impact your host.
You should be able to use Docker APIs for this (https://docs.docker.com/engine/api/) along with a framework that wraps the APIs. For example refer dockerode.
You could combine some JavaScript modules. node-pty and xterm being the most important. Additionally, ws is useful, but could be replaced but something else.
Note: this is not a production ready example. In particular, you should take care of safety measurements, or better yet, let no one but yourself use it.
server.js
import { WebSocketServer, createWebSocketStream } from 'ws';
import pty from 'node-pty';
const wss = new WebSocketServer({ port: 3000 });
wss.on('connection', (ws) => {
console.log('new connection');
const duplex = createWebSocketStream(ws, { encoding: 'utf8' });
const proc = pty.spawn('docker', ['run', "--rm", "-ti", "ubuntu", "bash"], {
name: 'xterm-color',
});
const onData = proc.onData((data) => duplex.write(data));
const exit = proc.onExit(() => {
console.log("process exited");
onData.dispose();
exit.dispose();
});
duplex.on('data', (data) => proc.write(data.toString()));
ws.on('close', function () {
console.log('stream closed');
proc.kill();
duplex.destroy();
});
});
index.html
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
<script src="node_modules/xterm/lib/xterm.js"></script>
</head>
<body>
<div id="terminal"></div>
<script type="module">
const term = new Terminal();
term.open(document.getElementById('terminal'));
const ws = new WebSocket('ws://localhost:3000');
ws.onmessage = async ({ data }) => term.write(await data.text());
term.onData((data) => ws.send(data));
</script>
</body>
</html>
Note: I am using the statics from the node modules folder, in your real code you probably want to use a bundler for this.
I am serving the entire project with nginx on port 8080 for simplicity. And then I start the server with node.
docker run -d --rm -p 8080:8080 -v "$PWD:/usr/share/nginx/html" nginxinc/nginx-unprivileged
node server.mjs
Afterwards, I can open http://localhost:8080 in my browser, and get a shell.
The dependencies in my package.json are these:
"dependencies": {
"node-pty": "^0.10.1",
"ws": "^8.7.0",
"xterm": "^4.18.0"
}
You can view the code in this repo: https://github.com/bluebrown/web-shell.

Sass built app/builds/application.css not making it into header

I am using the ruby Gem cssbundling-rails and dart-sass to process Sass in a Rails 7 app (and I am fairly new to Rails).
In the package.json file I define the build:css script:
"build:css": "sass ./app/assets/stylesheets/application.scss ./app/assets/builds/application.css --no-source-map --load-path=. --load-path=./node_modules --load-path=./node_modules/#rpf/sauce --load-path=app/assets/stylesheets/"
This appears to be working; I see the results of several Sass files bundled and processed into one CSS file: app/builds/application.css.
However I cannot see how to add this file to my page. We use Slim so I include the line
= stylesheet_link_tag 'application'
in the app/views/components/_head.html.slim file. That results in this fragment in the final HTML:
<link rel="stylesheet" href="/assets/application-e0cf9d8fcb18bf7f909d8d91a5e78499f82ac29523d475bf3a9ab265d5e2b451.css" />
If I load that file (application-e0cf9d8fcb18bf7f909d8d91a5e78499f82ac29523d475bf3a9ab265d5e2b451.css) into my browser I see it is an empty manifest file which starts
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
and has no files listed below.
What am I missing? How do I load the CSS that was bundled and processed from Sass files into the app/builds/application.css file into my Slim page?
A simple fix is to add
link rel="stylesheet" href="/assets/application.css" type="text/css"
to app/views/components/_head.html.slim instead.

What is the best way to use webpacker in a Rails engine?

I realise there is some debate about using webpacker in Rails engines but I have a simple usecase and currently have a workaround. Would like to know of a better (the best?) solution.
In this rails engine I have webpacker setup in the "spec/dummy" directory and everything works well in dev:
https://github.com/RealEstateWebTools/property_web_scraper/tree/master/spec/dummy/config/webpack
When the engine is used by a rails app however it will not find the compiled webpack files so each time I have a release ready I compile the webpack files and manually copy them to the vendor directory:
https://github.com/RealEstateWebTools/property_web_scraper/tree/master/vendor/assets/javascripts
I then require that file here:
https://github.com/RealEstateWebTools/property_web_scraper/blob/master/app/assets/javascripts/property_web_scraper/spp_vuetify.js
In my layout I use the above file using the good old sprockets "javascript_include_tag": https://github.com/RealEstateWebTools/property_web_scraper/blob/master/app/views/layouts/property_web_scraper/spp_vuetify.html.erb
In the layout there is a check to see if I'm running the "spec/dummy" app in which case I will user webpacker as it would normally be used in dev.
There must be a better way than this.
Webpacker has been retired
https://github.com/rails/webpacker
Going forward, it's better to switch to jsbundling-rails with webpack.
(I would rather suggest esbuild as it's "10×-100× faster")
But let's do it with webpack:
rails new webpack-in-engine --javascript webpack --css tailwind --database postgresql
In app/javascript/application.js I do:
console.log("hello from application.js")
And it works.
Now with an engine:
rails plugin new admin --mountable
Then depends:
Separate JS
Add an entry to your webpack.config.js:
const path = require("path")
const webpack = require("webpack")
module.exports = {
mode: "production",
devtool: "source-map",
entry: {
application: "./app/javascript/application.js",
admin: "./admin/app/javascript/admin.js"
},
output: {
filename: "[name].js",
sourceMapFilename: "[name].js.map",
path: path.resolve(__dirname, "app/assets/builds"),
},
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
]
}
<%= javascript_include_tag "admin", "data-turbo-track": "reload", defer: true %>
Shared JS
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
And in your app/javascript/application.js:
import "./../../admin/app/javascript/admin"
See full repo https://github.com/dorianmariefr/webpack-in-engine
Aside: Also I would rather namespace in the main app than have engines. I think engines are for very specific use cases not namespacing.

BrowserWindow in electron does not open

I just tried to test electron environment for programming with JavaScript on desktop with Windows 10.
So I have an app:
const electron=require("electron");
const app=electron.app;
const BrowserWindow=electron.BrowserWindow;
var mainWindow=null;
app.on("ready",function(){
mainWindow=new BrowserWindow({height:600,width:800});
mainWindow.loadURL("file://"+__dirname+"index.html");
});
and index.html is:
<html>
<head>
<title> MyIndex.html </title>
</head>
<body>
Hello World from Electron!<br>
</body>
</html>
and package.json is:
{
"name":"Electron-Test",
"version":"0.1.0",
"main":"./main.js",
"scripts":{"start":"electron ."}
}
If I run electron . or npm start the application seems to start, but no browser window opens. On console I have to press Ctrl-C to stop the application.
Does anyone know where is the problem?
try to add one more/after file:
you are also missing a / before index.html
app.on("ready",function(){
mainWindow=new BrowserWindow({height:600,width:800});
mainWindow.loadURL("file:///"+__dirname+"/index.html");
});
i saw it in this video, at 3:32 https://www.youtube.com/watch?v=i0AkgNv4U4E

AppCache html5, modifying the manifest file does not update the content of index.html?

From this link, it says :
Once an application is cached, it remains cached until one of the
following happens:
The user clears the browser's cache
The manifest file is modified (see tip below)
The application cache is programmatically updated
Following the instruction from the internet, for the manifest file I use a version number. When I change the content of the index.html with 01.jpg to 02.jpg - I also changed the version number of the manifest file.
With the steps above, it works within my Win7 Wamp Server Local Host. But once I do the same steps in my web server (after uploading the file to the web server) - it doesn't work.
Can somebody please help me what did I do wrong ?
Document was loaded from Application Cache with manifest http://www.example.com/test/offline.appcache
Application Cache Checking event
Navigated to http://www.example.com/test/
Application Cache NoUpdate event
Above is from the Chrome browser console after I modified the version number of the manifest file (from #01 to #02) and the jpg file (from 01.jpg to 02.jpg) in the index.html file.
The offline.appcache CACHE file list no change, except the version number :
CACHE MANIFEST
# 2017-03-25 version#01
uploads/event.jpg
uploads/baby.jpg
/favicon.ico
NETWORK:
indexPHP.php
The index.html file :
<!DOCTYPE html>
<html manifest="offline.appcache">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style></style>
</head>
<body>
<img src="uploads/01.jpg">
</body>
</html>
<script type="text/javascript">
function onUpdateReady() {
alert("offline files will be updated");
window.location.reload();
}
window.applicationCache.addEventListener('updateready', onUpdateReady);
if(window.applicationCache.status === window.applicationCache.UPDATEREADY) {
onUpdateReady();}
</script>
the .htaccess file :
AddType text/cache-manifest .appcache
the "tree" :
example.com/.htaccess
example.com/favicon.ico
example.com/test/index.html
example.com/test/offline.appcache
example.com/test/uploads/01.jpg
example.com/test/uploads/02.jpg
Thank you in advanced.

Resources