NestJS stuck on File change detected. Starting incremental compilation - nestjs

I'm having endpoint which is receiving file and store it in folder. However at the moment when add destination - where file to be stored and hit the endpoint server stuck and i receive this message: [17:54:47] File change detected. Starting incremental compilation...
This is how to controller looks like:
#ApiResponse({ type: CreateNFTRespDto })
#ApiBody({ type: CreateNFTReqDto })
#Post('upload')
#UseInterceptors(FileInterceptor('file', {
dest: './images'
}))
createNFT(
#UploadedFile() file: Express.Multer.File,
#Body() data: CreateNFTReqDto,
) {
return this._nftService.createNFT(file, data);
}
Any idea why is not able to compile, I think i had similar issue with the firebase and the reason there was the package was very big or something like this, could be the same with the Multer or so?

just add the file location folder in tsconfig.build.json as i did with 'media'
"exclude": ["node_modules", "test", "dist", "**/*spec.ts", "**/media"]

Related

How can you speed up webpack compilation (or separate it from server restart)

I currently have this setup:
import path from 'path'
import type {Configuration} from 'webpack'
const config: Configuration = {
mode: 'development',
entry: path.join(__dirname, '../..', 'dev/client.ts'),
output: {
path: path.join(__dirname, '../..', 'public'),
filename: 'script.js',
assetModuleFilename: '[name][ext]',
publicPath: '/',
libraryTarget: 'umd',
clean: false,
},
target: 'web',
resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx'],
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.(c|sc|sa)ss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
exclude: /node_modules/,
},
{
test: /\.(ico|svg|png|jpg)$/,
type: 'asset/resource',
},
],
},
stats: 'errors-warnings',
performance: {
hints: false,
maxAssetSize: 400000,
maxEntrypointSize: 400000,
},
devtool: 'source-map',
watch: true,
watchOptions: {
aggregateTimeout: 100,
poll: 1000,
followSymlinks: true,
ignored: /node_modules/,
},
}
export default config
Then I invoke the compiler with:
webpack(configuration, (error, stats) => {
if (error) {
console.log(error)
}
if (stats && stats.hasErrors()) {
console.log(stats.toJson().errors)
}
if (stats) {
console.log('Compiled in: ' + stats.toJson().time)
}
})
Which results in Compiled in: 4701 whenever you initially start up the server, after that whenever you make any file changes it'll be ~200ms to recompile it after webpack is already watching files, so it's only on the initial build.
Incremental builds is also already enabled.
Is there any way or any configuration I can do to decrease the compile time of the initial server startup? I want to run it along with ts-node-dev and my socket is refreshing the browser in ~100ms, so I don't want to wait 4 seconds on every server file change before I can see anything in browser but I also want to be able to run the client bundle and server using the same script and console, so the problem is every time you make any server file change it completely recompiles the client.
Currently I have tsnd --transpile-only src/dev/server.ts as my dev script. That index is building both the client and the server, which is what I want, however using tsnd on that file will cause the entire file to rebuild on server file changes and implicitly also rebuild the entire client (which isn't what I want). Is there another way I can set this up so that I can still run both using the same script but without rebuilding the entire client on server changes. I know that I can use nodemon and run them as separate processes but that sort of defeats the point of using ts-node-dev, is there an alternative option or something stupid that I'm not thinking about?
I'd also like to know if there's a way to disable type checking for ts-loader only during development mode in webpack, which is something that'll further speed it up. Well anything I can use to optimize it I'd really appreciate.
After more trial and error I finally found a solution using spawn.
import {spawn} from 'child_process'
const bundle = spawn('npm', ['run', 'bundle'])
bundle.stdout.on('data', (data) => {
console.log(data.toString('utf-8'))
})
bundle.stderr.on('data', (data) => {
console.error(data.toString('utf-8'))
})
bundle.on('close', (code) => {
console.log(code)
})
const server = spawn('npm', ['run', 'serve'])
server.stdout.on('data', (data) => {
console.log(data.toString('utf-8'))
})
server.stderr.on('data', (data) => {
console.error(data.toString('utf-8'))
})
server.on('close', (code) => {
console.log(code)
})
Along with:
"bundle": "node lib/dev/bundle.js",
"serve": "tsnd --transpile-only src/dev/server.ts",
"dev": "node lib/dev/index.js",`
This will allow you to separate your client bundle into one file, your tsnd server in another file, and to call both of them as child processes of the primary index. Now the server recompiles only on server file changes and the client recompiles only on client file changes and it's incredibly fast.
Though I don't know the caveats with doing it this way (it's the first time I'm spawning children like this), so I guess I'll figure out soon if there's any downside or issues with doing this. For now though everything everywhere recompiles and restarts under ~200ms.

ERR_INVALID_ARG_TYPE running criticalcss with webpack

With the following webpack.mix.js file
const mix = require("laravel-mix");
// Laravel Mix plugins for additional capabilities
require("laravel-mix-purgecss");
require("laravel-mix-criticalcss");
// CSS Plugins
const tailwindcss = require("tailwindcss");
const autoprefixer = require("autoprefixer");
const presetenv = require("postcss-preset-env");
mix.setPublicPath('../public_html/assets/')
.sass(pkg.paths.src.scss + "master.scss", "css/master.min.css")
.options({
processCssUrls: false,
postCss: [ tailwindcss('./tailwind.config.js') ],
})
.js(pkg.paths.src.js + "site.js", "js/site.min.js")
.sourceMaps()
.browserSync({
proxy: "domain.local",
notify: {
styles: {
top: 'auto',
bottom: '0'
}
},
files: [
"src/scss/*.scss",
"templates/*.twig",
"templates/**/*.twig",
"templates/*.js",
"templates/**/*.js"
]
});
// mix.disableSuccessNotifications();
if (mix.inProduction()) {
mix.webpackConfig({
plugins: [],
})
.criticalCss({
enabled: true,
paths: {
base: 'https://domain.local',
templates: './templates/_inline_css/',
suffix: '.min'
},
urls: [
{ url: '/', template: 'index' },
],
options: {
minify: true,
timeout: 1200000,
},
})
.version();
}
when I run npm run production I get:
98% after emitting HtmlCriticalWebpackPlugin(node:58149) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined.
What's confusing about this is that at one point this was working OK. My list of URLs is longer than what I've displayed above. And the first time I tried it, it successfully output CSS files but I was getting problems with timeouts so started doing a few at a time.
I was able to successfully run it two or three times before the above error appeared and now it won't compile anymore. I even went back and tried the same bundles I'd tried before but it wouldn't work the second time around.
I've also tried a similar set-up using Gulp but get the same error.
Has anyone else ever got this? How did you solve it?

How to handle ejs views using webpack

I'm trying to configure webpack with my website using node js, I'm using also ejs as a view. I have tried with many ways to handle the ejs in my webpack, but till now I didn't get success.
const path = require('path')
const nodeExternals = require('webpack-node-externals')
module.exports = (env, argv) => {
return ({
entry: {
server: './src/app.js',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: 'main.js'
},
mode: argv.mode,
target: 'node',
node: {
// Need this when working with express, otherwise the build fails
__dirname: true,
__filename: true,
},
externals: [nodeExternals()], // Need this to avoid error when working with Express
module: {
rules: [
{
// Transpiles ES6-8 into ES5
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.ejs$/,
loader: 'ejs-loader',
options: {
esModule: false
}
}
]
}
})
}
when I use HtmlWebPackPlugin I get some errors because of data inside <%- %> it's like he didn't know this data where comes from. like for example, <%- include('partials/head.ejs') %>.
is there a way to handle my views as ejs using webpack?
I know this has been asked a few months ago. But for those who come across this issue like I have, this is how I got this to work. Assuming your using webpack 4.
If you have not already install html-webpack-plugin
Most importantly to help solve the issue install raw-loader
add the following to your webpack config
new HtmlWebpackPlugin({
template: '!!raw-loader!./src/views/pages/<file-name-here>.ejs',
filename: 'index.ejs',
chunks: ['main', 'owl_carousel']
})
This is where the magic is. when including the template path make sure to include !!raw-loader! followed by the relative path.
raw-loader makes it so when html plugin creates the file it ignores the special syntax ejs uses. It is basically like "hey plugin ignore whatever I put here and just get me my file".
As #JRichardsz explained, You won't need Webpack explicitly to use EJS templates in your NodeJS project.
Also, It simply bundles up the EJS template (code) implicitly.
Try to bundle up your files with latest Webpack.js using below command to install:
npm install --save-dev webpack
Also, try this code with a little fix:
module.exports = (env, argv) => {
return ({
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: 'main.js'
}
...
// in case, all of this doesn't work. Then, explicitly whitelist EJS using regex
...
nodeExternals({
whitelist: [/\.(?|ejs)$)],
}),
...
})
}
If you want to use ejs for nodejs projects, you don't need webpack. Webpack is commonly used for client side rendering like angular, vue, react, etc
Check this: Which command should I use to minify and optimize nodejs express application? to view some ways to optimize your static js files used in ejs or another nodejs server rendering framework.
Basic structure for ejs projects is:
|____
|____server.js
|____views
| |____hello.ejs
|____package.json
hello.ejs a simple and plain template in which you can use any of ejs code like your
<%- include('partials/head.ejs') %>
As you can see, you don't need webpack to run ejs apps.
Check these samples:
minimal ejs sample
partials sample
You would need to make bundle of the EJS.
Try below commands:
module.exports = (env, argv) => {
return ({
output: {
path: './dist',
publicPath: '/',
filename: 'main.js'
}
})
}
copy-webpack-plugin worked perfectly
plugins: [
new webpack.ProgressPlugin(),
new CopyWebpackPlugin({
patterns: [
{from: "src/views", to: "views"}
]
})

nodejs upload image to bucket and give it 'shared publicity' property

Got some question related to uploading image and sharing it.
I found related question with answer, but it does now work. Google cloud responds with this error
NodeJS gcloud - Upload to google storage with public-read property/custom cache-expire
{ [Error: Required]
errors: [ { domain: 'global', reason: 'required', message: 'Required' } ],
code: 400,
message: 'Required',
response: undefined }
Ideally i want to upload a file, and then access it though public domain. I don't want to have any streaming solutions, as in like opening file through api.
// bucket is defined, uploading is fine
var file = bucket.file(id);
stream.pipe(file.createWriteStream());
//Giving permissions
bucket.acl.default.add({
scope: "allUsers",
role: gcloud.storage.acl.READER_ROLE
}, function(err) {
console.log(err);
// i am getting an error there
})
Thanks!

Load files in specific order with RequireJs

I'm new to RequireJS and I'm stuck with the loading order.
I have a global project configuration that I need to be loaded before the modules located in js/app/*.
Here's my struture :
index.html
config.js
js/
require.js
app/
login.js
lib/
bootstrap-2.0.4.min.js
Here's the config.js file :
var Project = {
'server': {
'host': '127.0.0.1',
'port': 8080
},
'history': 10, // Number of query kept in the local storage history
'lang': 'en', // For future use
};
And here's my requirejs file (app.js) :
requirejs.config({
//By default load any module IDs from js/lib
baseUrl: 'js/lib',
//except, if the module ID starts with "app",
//load it from the js/app directory. paths
//config is relative to the baseUrl, and
//never includes a ".js" extension since
//the paths config could be for a directory.
paths: {
bootstrap: '../lib/bootstrap-2.0.4.min',
app: '../app',
},
shim: {
'app': {
deps: ['../../config'],
exports: function (a) {
console.log ('loaded!');
console.log (a);
}
} // Skual Config
},
});
var modules = [];
modules.push('jquery');
modules.push('bootstrap');
modules.push('app/login');
// Start the main app logic.
requirejs(modules, function ($) {});
But sometimes, when I load the page, I have a "Project" is undefined, because login.js has been loaded BEFORE config.js.
How can I force config.js to be loaded at first, no matter what ?
Note: I saw order.js as a plugin for RequireJS but it's apparently not supported since the v2, replaced by shim.
Ran into a similar problem today - we have bootstrapped data that we want to make sure is loaded before anything else, and that the module exposing that data is set up before any other modules are evaluated.
The easiest solution I found to force load order is to simply require a module be loaded before continuing on with app initialization:
require(["bootstrapped-data-setup", "some-other-init-code"], function(){
require(["main-app-initializer"]);
});
There's a possible solution to build a queue for modules to be loaded. In this case all modules will be loaded one-by-one in exact order:
var requireQueue = function(modules, callback) {
function load(queue, results) {
if (queue.length) {
require([queue.shift()], function(result) {
results.push(result);
load(queue, results);
});
} else {
callback.apply(null, results);
}
}
load(modules, []);
};
requireQueue([
'app',
'apps/home/initialize',
'apps/entities/initialize',
'apps/cti/initialize'
], function(App) {
App.start();
});
You won't have to worry about the load order if you define your js files as AMD modules. (Or you can use the shim config if you can't modify the config.js and login.js to call define).
config.js should look something like this:
define({project: {
'server': {
'host': '127.0.0.1',
'port': 8080
},
'history': 10, // Number of query kept in the local storage history
'lang': 'en', // For future use
}});
login.js:
define(['jquery', '../../config'], function($, config) {
// here, config will be loaded
console.log(config.project)
});
Again, shim config should only be used if calling define() inside the modules is not an option.

Resources