Webpack hot module replacement through Django template - django

I'm trying to set up hot module replacement for my bundled frontend static assets that are served through Django's template system, if that's even possible. I'm currently refreshing the page via livereload whenever the compiled assets are changed, but the compile times are getting longer and any CSS changes end up triggering a full page reload.
Here is an example of the template file in Django.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- Header Links -->
</head>
<body>
<div id="app"></div>
<script type="text/javascript">
window.CONFIG = {
/** Injected application configuration from Django. */
};
</script>
<!-- Webpack bundle url -->
<script src="{{ bundle_url }}"></script>
</body>
</html>
I've been able to serve the assets through webpack dev server and inject the bundle url http://localhost:3000/bundle.js through template variables, so I can see the application in the view.
Webpack Configuration
'use strict';
const webpack = require('webpack');
const CONFIG = require('./config');
/**
* Webpack configuration for a development environment.
* #type {Object}
*/
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
require.resolve('core-js/shim'),
CONFIG.PATHS.ENTRY,
],
output: {
path: CONFIG.PATHS.BUILD,
filename: CONFIG.OUTPUT_FILENAME,
},
module: {
rules: CONFIG.SHARED_RULES.concat([{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}, {
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}]),
},
resolve: CONFIG.WEBPACK_RESOLVE,
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
};
Start Script:
'use strict';
// Crashes the script on unhandled rejections instead of silently ignoring.
process.on('unhandledRejection', (error) => { throw error; });
process.env.NODE_ENV = 'development';
// Vendor
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const chalk = require('chalk');
// Local
const WEBPACK_CONFIG = require('../config/webpack.config.dev');
const CONFIG = require('../config/config');
const PORT = parseInt(process.env.PORT, 10) || CONFIG.DEFAULT_PORT;
const HOST = process.env.HOST || CONFIG.DEFAULT_HOST;
const URL = `http://${HOST}:${PORT}/`;
const compiler = webpack(WEBPACK_CONFIG);
const server = new WebpackDevServer(compiler, {
compress: true,
hot: true,
host: HOST,
stats: 'minimal',
});
server.listen(PORT, HOST, (error) => {
if (error) { return console.log(chalk.red(error)); }
console.log(chalk.cyan(`Starting the development server at ${URL}...`));
['SIGINT', 'SIGTERM'].forEach((signal) => {
process.on(signal, () => {
server.close();
process.exit();
});
});
});
I'm uncertain how the dev server triggers a hot reload. I was under the impression that the bundle includes a script that connects to a Websocket connection on the dev server and that the connection would trigger the script to download and display the new assets. This may not be the case though, and I haven't been able to find any info pertaining to how hot reloads are communicated. I've only found a general overview of how hot reloads work once the client receives the update.

After a lot of searching, I finally found a solution to my problem. I found information about how to integrate webpack-dev-server with an existing server in the old webpack docs, so I got rid of the entire build script and replaced it with a script in package.json that only used webpack-dev-server without any flags at all:
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server",
// Scripts...
}
This automatically injected the hot module replacement code into my bundle and refreshes my page on a change. This is much faster than my previous livereload server. The bundle is referenced via the url http:localhost:8080/bundle.js in my application template and not by a local path. Local paths wouldn't work anyways since the bundles are saved in memory.
The url also explains how to get the --inline --hot functionality working too, but I was never able to get it to work on my setup.
If you need to use local path's instead of referencing the bundles via url, than you would have to rely on using webpack's watch mode and manually refreshing the page or rely on a Django plugin. The solution I found worked well for me because it mirrors our production environment. Our Django deployment references the frontend assets through a CDN that we manage. It may not work well for you if you have to deploy the frontend assets with your Django code, but it's possible if you create a Django setting that toggles between two different application templates: one for development that uses the URL to pull in the script and one for production that references the files from the STATICFILES_DIRS.

The problem I don't think is Webpack's fault. I've noticed these speed problems occur when I had Django serve my React files. When you use Django, your files are served by the Django server, and that inherently is pretty slow compared to the webpack-dev server. The whole communication process between webpack dev server to Django can be time taking, which has to have the Django server to trigger a change and then re-serve the static files again.
One solution to this would be to isolate React front end code from the backend code and have your React consume your Django's REST API. It runs extremely smooth and reduces a lot of load on the server.

Related

vuejs app with vue router hosted on amplify direct url to file doesn't work

I have an issue on which I struggled all day long, I have a VueJS app with vue router that I host on amplify?
everything working great Except that
I need to give a direct access to a file (I want to register an Apple merchant ID with stripe)
I tried to create a route in my route/index.js with my file name that redirect to a component that open the merchantid file with an windows.open('myfile').
it works great on local serve and build but not once deployed through amplify built with webpack
//router/index.js
import WellKnown from '#/components/AppleVerification.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/.well-known/apple-app-site-association',
component: WellKnown,
}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router
// AppleVerification.vue
<template>
<div></div>
</template>
<script>
export default {
name: 'WellKnown',
props: {
file: String
},
mounted () {
window.open('file:///.well-known/apple-developer-merchantid-domain-association')
}
}
</script>
so I went to amplify console and make a redirection with first priority to the URL and target address to the file. but it didn't work also.
I went out of ideas on how to give access to a file in my sources with a direct URL.
would appreciate a little help
thanks
You issue comes from the acces to the file througth Amplify for several reasons.
Try following:
rename your endfile "apple-developer-merchantid-domain-association"
with an extension like
apple-developer-merchantid-domain-association.txt
remove the dot in your path public/.well-known/apple-developer-merchantid-domain-association to public/well-known/apple-developer-merchantid-domain-association.txt
in your amplify console create a priority 1 rule that redirects your
https://mydomain/.well-known/apple-developer-merchantid-domain-association to
/well-known/apple-developer-merchantid-domain-association.txt with a 202 rexrite method.
It should work
You even didn't need the component anymore

emberjs add bootstrap template javascript

I have a bootstrap template with custom css and js that I want to use with ember.js.
I am stuck with integrating the js.
I have to say that I usually don't work on the frontend side, so if this is an obvious mistake I made, excuse me.
I want to stick with the js I have from the template and don't want to include ember-bootstrap for example.
node version: v14.15.5, ember-cli: 3.25.0
npm packages to include: bootstrap#5.0.0-beta2, flickity, flickity-imagesloaded, flickity-as-nav-for, flickity-fade, jarallax
I have identified two tasks here. First, I need to integrate the existing npm packages. Then I need to add the custom scripts.
Current status
1. Packages
I added the npm packages to ember-cli-build.js over app.import()
// ember-cli-build.js file
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function (defaults) {
let app = new EmberApp(defaults, {});
app.import("node_modules/bootstrap/dist/js/bootstrap.min.js");
app.import("node_modules/jarallax/dist/jarallax.min.js", {
using: [{ transformation: 'cjs', as: 'jarallax' }]
});
app.import("node_modules/flickity/dist/flickity.pkgd.min.js");
app.import("node_modules/flickity-as-nav-for/as-nav-for.js");
app.import("node_modules/flickity-fade/flickity-fade.js");
app.import("node_modules/flickity-imagesloaded/flickity-imagesloaded.js");
return app.toTree();
};
When I go to the debug tab in my browser I see the packages are getting loaded under assets/node_modules/.. but js does not have any effect.
I tried to load the package in index.html over a script tag:
<script type="text/javascript" src="{{rootURL}}assets/node_modules/flickity/dist/flickity.pkgd.min.js"></script>
I get the error in the browser console window:
Refused to execute http://localhost:4200/assets/node_modules/flickity/dist/flickity.pkgd.min.js as script because "X-Content-Type-Options: nosniff" was given and its Content-Type is not a script MIME type.
2. Custom js scripts
The custom scripts have a moin theme.js script that imports everything else.
// js/theme.js
// Theme
import './aos';
import './bigpicture';
// ...
The imported Javascript scripts from theme.js also have imports like
// js/aos.js (imported from theme.js)
import AOS from 'aos';
const options = {
duration: 700,
easing: 'ease-out-quad',
once: true,
startEvent: 'load'
};
AOS.init(options);
The original theme.js also had import for Bootstrap and the other libraries.
// js/theme.js
// Vendor
import 'bootstrap';
import 'flickity';
// ...
import 'jarallax';
// Theme
import './aos';
import './bigpicture';
// ...
I had the js directory under vendor, public and app the import via the script tag did not work either. Importing from app.js has no effect.

Webpack use folder name instead of Url for public path

I am using react and django. I am trying to use code-splitting in my components, so in my webpack.config.js I have this
output: {
path: path.join(__dirname, "frontend/static/frontend"),
filename: "[name].bundle.js",
chunkFilename: "[name].chunk.js",
publicPath: "/frontend/static/frontend/"
},
but when it requests it in the browser it goes to
/en/account/quiz/drug-abuse/frontend/static/frontend/2.chunk.js
instead of
static/frontend/2.chunk.js
my javascript files are located in my static folder for django but react routing starts at /en/, I am guessing that is why the confusion is happening.
Is there anyway to make the webpack file look for
http://domainblahblah.com/static/frontend/2,chunk.js

auto-refresh (gulp+livereload+jasmine)

I'm trying to creat a gulp task to run a test and automatically refresh when changes occur in any .js test file.
This is the code:
gulp.task('watch-test', function() {
// start live-reload server
plugins.livereload.listen({ start: true});
var filesForTest = [ 'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'src/app/blocks/testController.module.js',
'src/app/blocks/testController.js',
'src/test/spec/sillyControllerSpec.js']
return gulp.src(filesForTest)
.pipe(watch(filesForTest))
.pipe(plugins.jasmineBrowser.specRunner())
.pipe(plugins.jasmineBrowser.server({port: 8888}))
.pipe(plugins.livereload());
});
It watches the files, but I have to refresh manually the page at the browser.
Any idea what can I do?
I found this package that incluide jasmine + livereload
https://www.npmjs.com/package/gulp-jasmine-livereload-task

using baseUrl affects the path to my assets

I'm integrating an ember-cli app inside my main site which will be accessible at url http://host/faq/....ember...routes
So I added baseUrl: /faq/ to my ember
config/environment.js
module.exports = function(environment) {
var ENV = {
modulePrefix: 'faq',
environment: environment,
baseURL: '/faq/',
locationType: 'hash',
The problem: While developing in my ember-cli environment with ember server my assets such as (SVG, FONTS and IMAGES) are giving me a NOT FOUND now.
For example: http://host/assets/images/bg.png gives me a not found it now expects http://host/faq/assets/images/bg.png. Why is this happening?
If you want to serve assets from the root, leave base url as: baseURL: '/'.
Then, to customize the urls for your ember app, configure rootURL on the Router instance (app/router.js): rootURL: '/faq/'
http://emberjs.com/guides/routing/#toc_specifying-a-root-url
I had the same problem with this project: Ember-Material-Navigation
I fixed this issue by defining a baseUrl variable in my main sass file and concatenating to all external urls.
$baseUrl: "/faq/";
#include font-face("Font Name", font-files($baseUrl + "/dir/font.ttf"));
However, this only works if you are using sass.