Using a Svelte build with a Sails node server - sails.js

I am trying to set up a website with Svelte for the frontEnd and Sails for the backend.
My problem is that I can't display my Svelte public build as my Sails default web page.
I want to keep the organization below (or maybe something similar) and have my Svelte public build page when I go on 'http://myserver:1337' instead of having the default Sails page : file organization
PS: I am using Node: v14.4.0, Sails: v1.2.4 and Svelte: v6.14.5.
Thank you all :)

You could try something like:
Compile Svelt to build into the /public directory on Sails.js.
Open your rollup.config.js and change the path of your public/build/bundle.js and public/build.bundle.css to the public sails path, i.e. "../server/public...".
Configure /task/pipeline.js to include the compiled js and css files:
// tasks/pipeline.js
var cssFilesToInject = [
'css/**/global.css',
'css/**/bundle.css',
'css/**/*.css',
];
var jsFilesToInject = [
'js/**/bundle.js',
'js/**/*.js'
];
Create a controller to load the index file:
// router.js
'/*': { action: 'index', skipAssets: true, skipRegex: /^\/api\/.*$/ },
The excluded "/api" routes is to allow you to configure the CRUD routes.
The index controller:
module.exports = {
friendlyName: 'View homepage',
description: 'Display a compiled index page',
exits: {
success: {
statusCode: 200,
viewTemplatePath: 'pages/index'
},
},
fn: async function () {
return {};
}
};
And the index page you could include the template index.html or create your own index.ejs to load the static content, the same you configured before:
// views/templates/template.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<!--STYLES-->
<!--STYLES END-->
</head>
<body>
<!--TEMPLATES-->
<!--TEMPLATES END-->
<%- body %>
<!-- exposeLocalsToBrowser ( ) %>
<!--SCRIPTS-->
<!--SCRIPTS END-->
</body>
</html>
And the index.ejs:
// views/pages/index.ejs
<!-- Nothing here I mean -->

Thank you for your answer it helps me to understand how does it works.
I am sorry but I did not follow your tutorial exactly (because I was not able to understand what I was supposed to do ;) ).
I edit the rollup.config.js as :
import svelte from 'rollup-plugin-svelte';
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
const production = !process.env.ROLLUP_WATCH;
const BUILD_PATH = '../server/assets';
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: `${BUILD_PATH}/build/bundle.js`
},
plugins: [
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file - better for performance
css: css => {
css.write(`${BUILD_PATH}/build/bundle.css`);
}
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload(BUILD_PATH),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
}
}
};
}
And I move my files is the assets as :
file organization
Then I deleted the homepage.ejs in server/views/pages/
And it works :) !
Thank you again for your quick answer

Related

Perl - Mojolicious Webpack Can't load application from file [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
mojo webpack script\one_commex
Web application available at http://127.0.0.1:3000
Can't exec "C:\Users....\Box Sync\projects\perl_projects\mojo_projects\one_commex\node_modules.bin\webpack": No such file or directory at C:/Strawberry/perl/site/lib/Mojolicious/Plugin/Webpack/Builder.pm line 214.
Can't load application from file "C:\Users....\Box Sync\projects\perl_projects\mojo_projects\one_commex\script\one_commex": [Webpack] exec C:\Users...\Box Sync\projects\perl_projects\mojo_projects\one_commex\node_modules.bin\webpack --config C:\Users...\Box Sync\projects\perl_projects\mojo_projects\one_commex\webpack.config.js --watch: No such file or directory at C:/Strawberry/perl/site/lib/Mojolicious/Plugin/Webpack/Builder.pm line 215.
Compilation failed in require at (eval 107) line 1.
[Webpack] Could not find C:\Users...\Box Sync\projects\perl_projects\mojo_projects\one_commex\public\asset\webpack.development.html. Sure webpack has been run? at C:/Strawberry/perl/site/lib/Mojolicious/Plugin/Webpack.pm line 87.
It works in Ubuntu machine correctly.
In windows, webpack installs the packages, creates assets directory, webpack.custom.js, creates a directory in public as "asset". But, it throws the error.
I have been able to find the solution based on the trick that I learnt from setup done for my django project.
Manually created webpack.config.js for the common (development) settings and webpack.prod.config.js for the production along with package.json in the mojolicious project root directory
my webpack.config.js looks like below:
var path = require("path");
var webpack = require("webpack");
var BundleTracker = require("webpack-bundle-tracker");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
var { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
context: __dirname,
entry: './public/javascripts/index',
output: {
path: path.resolve('./public/bundles/'),
filename: "[name].js"
},
resolve: {
alias: {
'jquery': path.join(__dirname, 'node_modules/jquery/src/jquery')
}
},
plugins: [
new BundleTracker({
filename: './webpack-stats.json'
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
jquery: "jquery",
"window.jQuery": "jquery",
Highcharts: 'highcharts',
}),
new MiniCssExtractPlugin({
filename: `[name].css`
}),
new CleanWebpackPlugin()
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.(woff(2)?|eot|ttf|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{
loader: 'url-loader',
}
],
},
{
test: /\.(sass|scss|css)?$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: './bundles',
}
},
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: {
plugins: function () { // post css plugins, can be exported to postcss.config.js
return [
require('precss'),
require('autoprefixer')
];
}
}
},
{ loader: 'resolve-url-loader' },
{ loader: 'sass-loader' }
]
},
{
test: /\.(jpe?g|png|gif)$/i,
use: ['file-loader']
},
],
},
}
my layout template default.html.ep looks like this
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
%= include 'layouts/_mojo_default'
<link type="text/css" rel="stylesheet" href="/bundles/main.css">
</head>
<body>
<%= content %>
<h1 class="text-primary">All OK!<h1>
<script type="text/javascript" src="/bundles/main.js"></script>
</body>
</html>
Then, added the following scripts in my package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.config.js --mode development",
"build-watch": "webpack --config webpack.config.js --mode development --watch",
"build-production": "webpack --config webpack.prod.config.js --mode production"
},
So, now I can open one console for running the following which takes care of building packages as and when the front-end codes change
> npm run build-watch
In other console, I run the following:
> morbo script\<app>
Before deployment, I will run the following:
> npm run build-production
And change my default.html.ep (though dynamic way can be done with the help of server side operation)
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
%= include 'layouts/_mojo_default'
<link type="text/css" rel="stylesheet" href="/dist/main.css">
</head>
<body>
<%= content %>
<h1 class="text-primary">All OK!<h1>
<script type="text/javascript" src="/dist/main.js"></script>
</body>
</html>
That's it!

How to integrate Material UI into Svelte project

I want to integrate Material UI into my Svelte project.
I tried to follow the official documentation from here, but I don't know why I'm getting a strange error while trying to run my project:
loaded rollup.config.js with warnings
(!) Unused external imports
default imported from external module 'rollup-plugin-postcss' but never used
rollup v1.27.13
bundles src/main.js → public/build/bundle.js...
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src/views/App.css (1:0)
1: .footer.svelte-1xl6ht0{position:fixed;left:0;bottom:0;width:100%;background-color:#569e3e;color:white;text-align:center;height:15px}.footer.us.svelte-1xl6ht0,.footer.europe.svelte-1xl6ht0,.footer.central.svelte-1xl6ht0,.footer.south.svelte-1xl6ht0,.footer.apac.svelte-1xl6ht0,.footer.baldr.svelte-1xl6ht0{background-color:#ca4a4a}.footer
....
The problem seems to be related to CSS.
In my src directory I have a directory called theme which contains a file called _smui-theme.scss and this is the content of the file:
#import "#material/theme/color-palette";
// Svelte Colors!
$mdc-theme-primary: #ff3e00;
$mdc-theme-secondary: #676778;
// Other Svelte color: #40b3ff
$mdc-theme-background: #fff;
$mdc-theme-surface: #fff;
$mdc-theme-error: $material-color-red-900;
And here is my rollup.config.json file:
import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import json from '#rollup/plugin-json';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js',
},
plugins: [
json(),
svelte({
// Enables run-time checks when not in production.
dev: !production,
// Extracts any component CSS out into a separate file — better for performance.
css: css => css.write('public/build/bundle.css'),
// Emit CSS as "files" for other plugins to process
emitCss: true,
}),
resolve({
browser: true,
dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/')
}),
commonjs(),
// In dev mode, call `npm run start` once the bundle has been generated
!production && serve(),
// Watches the `public` directory and refresh the browser on changes when not in production.
!production && livereload('public'),
// Minify for production.
production && terser()
],
watch: {
clearScreen: false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
}
}
};
}
In order to solve this issue a postcss plugin is needed for rollup.
I have also added a svelte preprocessor (I think this is optional, but I wanted to be sure).
Make sure you install this packages with npm or yarn:
rollup-plugin-postcss and svelte-preprocess
Then the plugins should be added in rollup.config.js like this:
import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss'; <<<------------- Add this
import autoPreprocess from 'svelte-preprocess'; <<<------------- Add this
import json from '#rollup/plugin-json';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js',
},
plugins: [
json(),
svelte({
// Enables run-time checks when not in production.
dev: !production,
// Extracts any component CSS out into a separate file — better for performance.
css: css => css.write('public/build/bundle.css'),
// Emit CSS as "files" for other plugins to process
emitCss: true,
preprocess: autoPreprocess() <<<------------- Add this
}),
resolve({
browser: true,
dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/')
}),
commonjs(),
postcss({ <<<------------- Add this
extract: true,
minimize: true,
use: [
['sass', {
includePaths: [
'./src/theme',
'./node_modules'
]
}]
]
}),
// In dev mode, call `npm run start` once the bundle has been generated
!production && serve(),
// Watches the `public` directory and refresh the browser on changes when not in production.
!production && livereload('public'),
// Minify for production.
production && terser()
],
watch: {
clearScreen: false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
}
}
};
}
Now everything should be working right with the css and Material UI can be used.

sails doesnt not auto insert dependencies with handlebars

I'm trying to use handlebars for the templating engine but sails does not seem to insert the files in the dependency folder.
/config/views.js:
engine: 'handlebars',
layout: false,
partials: false
/views/login.handlebars:
<!DOCTYPE html>
<html>
<head>
<!--STYLES-->
<!--STYLES END-->
</head>
<body>
<p>Handlebars</p>
<!--SCRIPTS-->
<!--SCRIPTS END-->
</body>
</html>
/assets/js/dependencies contains:
bootstrap.min
jquery.min
sails.io.js
When I go to the rendered page after lifting sails the files are not populated in between the scripts tag.
Thanks!!
You should update your tasks/config/sails-linker.js and replace all occurrences of ".ejs" with ".handlebars"
E.g. from:
devJs: {
options: {
startTag: '<!--SCRIPTS-->',
endTag: '<!--SCRIPTS END-->',
fileTmpl: '<script src="%s"></script>',
appRoot: '.tmp/public'
},
files: {
'.tmp/public/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.ejs': require('../pipeline').jsFilesToInject // <- HERE
}
},
to
devJs: {
options: {
startTag: '<!--SCRIPTS-->',
endTag: '<!--SCRIPTS END-->',
fileTmpl: '<script src="%s"></script>',
appRoot: '.tmp/public'
},
files: {
'.tmp/public/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.handlebars': require('../pipeline').jsFilesToInject // <-HERE
}
},
See also this page (where the original answer comes from).
https://mtjburton.co.uk/post/sailsjs+handlebarsjs/

RequireJS optimizer fails to load external facebook js correctly

My file structure looks like this. Everything is inside the js folder.
-js
--config.js
-app
--app.fb.js
--main.js
-lib
--jquery-1.9.0.js
--require.js
-tools
--r.js
--build.js
I've created a config file as per https://developers.facebook.com/docs/javascript/howto/requirejs
config.js
require.config({
shim: {
'facebook' : { exports: 'FB' }
},
paths: {
'jquery': '../lib/jquery-1.9.0',
'facebook': '//connect.facebook.net/en_US/all'
}
});
app.fb.js
define(['facebook'], function(){
console.log("loaded fb");
});
build.js
({
baseUrl: "../app",
mainConfigFile: "../config.js",
name: "main",
out: "../core.js",
paths: {
'facebook': 'empty:'
}
})
main.js
require(["jquery", "app.fb"], function($, appfb){
// Log the callback parameter.
console.log( "$.fn.jquery:", $.fn.jquery );
});
finally I call the optimized file(core.js) here
<script type="text/javascript" data-main="js/core" src="js/lib/require-2.1.15.js"></script>
The optimizer appears to run correctly but when I load the page I expect the Facebook module to load in from the CDN. Instead I get
GET http://example.com/js/facebook.js require-2.1.15.js:1901
Uncaught Error: Script error for: facebook
I've spent ages on this and can't figure out the problem!
Any thoughts?
Thanks
Got it, for some reason this only worked when I moved the config.js contents into main.js.
This looks like:
require.config({
shim: {
'facebook' : { exports: 'FB' }
},
paths: {
'jquery': '../lib/jquery-1.9.0',
'facebook': '//connect.facebook.net/en_US/all'
}
});
require(["jquery", "app.fb"], function($, appfb){
// Log the callback parameter.
console.log( "$.fn.jquery:", $.fn.jquery );
});
In build.js, change
mainConfigFile: "../app/config.js",
to
mainConfigFile: "../app/main.js",
r.js optimiser runs correctly!

Unable to Execute Jquery from sidebar in Addon Firefox SDK

I am new to this Firefox SDK , but what i have understood you can execute content Scripts on Pages.
Here is the Code
MAIN.JS
var tabs = require("sdk/tabs");
var data = require("sdk/self").data;
var sidebar = require("sdk/ui/sidebar").Sidebar({
id: 'my-sidebar',
title: 'My sidebar',
url: data.url("index.html"),
onReady: function (worker) {
worker.port.emit('turl',tabs.activeTab.url);
}
});
SIDEBAR.JS
$('#bt1').on('click',function(){
$('title').textContent;
});
INDEX.HTML
<!DOCTYPE HTML>
<html>
<body>
<input type="button" id="bt1" value="Click Me"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="sidebar.js"></script>
</body>
</html>
But this code tries to find out title of the Sidebar html.
I have also tried using contentScriptFile in Main.js but same thing happened
var tabs = require("sdk/tabs");
var data = require("sdk/self").data;
var sidebar = require("sdk/ui/sidebar").Sidebar({
id: 'my-sidebar',
title: 'My sidebar',
url: data.url("index.html"),
contentScriptFile: [data.url("jquery.min.js"),data.url("sidebar.js")],
onReady: function (worker) {
worker.port.emit('turl',tabs.activeTab.url);
}
});
The Jquery code is in the sidebar.js
Still no Results.Please help
There is no contentScriptFile for the Sidebar class.
Try this: copy the jquery library to a local file in the data folder, then refer to it using a relative path. Sidebars can only use 'local' JS, they cannot load scripts from the internet.