vue + webpack: how the dynamic component import works? - django

I use combination of Django+Vue, and I struggle to understand how do names that are created by vue-cli-service build or vue-cli-service serve are created and work, and how to set this in production.
If I do not have dynamic component imports, everything works smoothly.
My vue.config.js looks like that:
module.exports = {
pages: {
main: {
entry: "./src/main.js",
chunks: ["chunk-vendors"],
},
},
// Should be STATIC_URL + path/to/build
publicPath: "/front/",
// Output to a directory in STATICFILES_DIRS
outputDir: path.resolve(__dirname, "../_static/front/"),
// Django will hash file names, not webpack
filenameHashing: false,
productionSourceMap: false,
runtimeCompiler: true,
devServer: {
writeToDisk: true, // Write files to disk in dev mode, so Django can serve the assets
},
};
The result of built looks like that:
And I simply refer to these files in a Django template:
<div id="app"></div>
<script type="text/javascript" src="{% static 'front/js/chunk-vendors.js' %}"></script>
<script type="text/javascript" src="{% static 'front/js/main.js' %}"></script>
But as soon as I start using dynamic components, like that:
const User = () => import("./components/User")
Everything stops working, and in addition webpack creates some js files with hashed names in a static folder, and I can't figure out the logic (so I can't refer to them in the template.

Webpack has so called 'magic comments' - see here https://webpack.js.org/api/module-methods/#magic-comments
What you have there are not really dynamic routes, but lazy ones, which means their code is written into chunks rather than in the main js file and only loaded, when the component is loaded.
So to create a named chunk, you can write the import like that:
import(/* webpackChunkName: "about" */ "../views/About.vue")
However, you'll still have a hash value after that. This is done to avoid browser caching - the browser would not know that there is a new version of the file if it has the same name under certain conditions (like no etags set etc.) This is a webpack configuration that can be overwritten in the vue config. You can have a look for that here: https://github.com/vuejs/vue-cli/issues/1649
Edit: as I just saw you can even disable it with the filenamehashing config key: https://cli.vuejs.org/config/#filenamehashing

Related

Ember-index is not producing index.jsp

I am trying to use ember-index add on to generate index.jsp file instead of index.html. I have installed the ember-index addon and did the required changes as well.
My config/environment.js file looks like below
/* eslint-env node */
'use strict';
module.exports = function(environment) {
let ENV = {
modulePrefix: 'user-profile',
output: 'index.jsp',
environment,
rootURL: '/',
locationType: 'hash',
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
},
EXTEND_PROTOTYPES: {
// Prevent Ember Data from overriding Date.parse.
Date: false
}
},
'ember-index': {
output: 'index.jsp',
content: {
file: 'example.txt',
includeInOutput: true,
includeInIndexHtml: false
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
}
};
return ENV;
};
Also my example.txt file looks like
<meta content="Example">
<h2>html to jsp</h2>
and finally in my index.html I have added below snippet
{{content-for 'ember-index'}}
But now when i am trying to build the ember project with ember build I am not able to see index.jsp file in my dist folder.
With a fresh app, this addon works as expected. Walk through the steps for the minimal example using a new Ember app, and you'll find what you missed.
Are you sure you're looking in the right place for the index.jsp? It is at dist/export/index.jsp after running ember build.
Did you forget to add the tag in your index.html? The readme specifies that for your files to be used, they must be specified like this:
<!-- app/index.html -->
<!DOCTYPE html>
<html>
<head>
...
{{content-for 'ember-index-1'}}
{{content-for 'ember-index-2'}}
</head>
<body>
...
</body>
</html>

django-wysiwyg-redactor doesn't work in inlines

So I am using django-wysiwyg-redactor==0.4.9 and Django==1.9.
The issue described here.
I tried a trick in comments, but that didn't help.
Also in browser's console I run this code directly to needed textarea:
$('#id_outboundprogram_set-2-text').trigger('redactor:init');
But anyway there are no redactor on it.
Textarea element looks like this before and after running above code:
<textarea class=" redactor-box" cols="40" data-redactor-options="{"lang": "en", "fileUpload": "/en/redactor/upload/file/", "imageUpload": "/en/redactor/upload/image/", "plugins": ["table", "video"]} id="id_outboundprogram_set-2-text" name="outboundprogram_set-2-text" rows="10"></textarea>
Strange thing is that this code, that I found in jquery.redactor.init.js from package files is not working:
// Initialize Redactor on admin's dynamically-added inline
// formsets.
//
// Credit to the approach taken in django-selectable:
// https://github.com/mlavin/django-selectable
$(document).on('click', '.add-row', function () {
$(this).parents('.inline-related')
.find('tr.form-row:not(.empty-form)').last()
.find('textarea.redactor-box')
.trigger('redactor:init');
});
Any ideas?
UPD:
Well, I still don't know why it happpens, but I solved this problem by including redactor.js file from package files and adding a little changes to above script:
<script type="text/javascript" src="{% static 'js/admin/redactor.js' %}"></script>
var program_tab = $('#outboundprogram_set-group'); // this is just because I have several inlines
program_tab.children('.add-row').on('click', function(){
program_tab.children('.inline-related:not(.empty-form)')
.last()
.find('textarea.redactor-box')
.redactor();
});
UPD 2:
Using this soution there is no plugins and image/file handlers. So I researched a little and found this article.
But image and file handling already implemented in django-wysiwyg-redactor, so I need just to use RedactorUploadView(). Urls can be found in urls.py file from sources. So here is the code:
var program_tab = $('#outboundprogram_set-group');
program_tab.children('.add-row').on('click', function(){
program_tab.children('.inline-related:not(.empty-form)')
.last()
.find('textarea.redactor-box')
.redactor({
imageUpload: "{% url 'redactor_upload_image' 'tours/out/programs/img/' %}",
fileUpload: "{% url 'redactor_upload_file' 'tours/out/programs/files/' %}",
plugins: ['table', 'video', 'fullscreen', 'image']
});
});

Managing 'window' object in Isomorphic App with ReactJS and Flask Python

I am developing an application with Flask Backend with ReactJS front.
ReactJS app has been developed and bundled with webpack.
Everything works fine with client side rendering which is bundled with webpack.
I am now trying to add server side rendering with python-react .
But problem is, I have to share some variables to my ReactJS app via Jinja2 template in base template index.html which has the reactjs root component node <div id='react-node'></div>.
I had to send my routes and config to my application via jinja2 template like below ,
//index.html
<!doctype html>
<html>
...
...
<script type='text/javascript'>
var STATIC_IMAGE_ROOT = "{{ url_for('static', filename='img/') }}";
var ROUTES = { ... };
...
</script>
</html>
All the above js variables are being set to global window object .
But when I am trying to render the component in python, it throws exception for window object ReactRenderingError: react: ReferenceError: window is not defined .
What is the best way to solve this issue ?
There is no window global when rendering on the server. You can create a fake window, first checking if the window exists:
if (typeof(window) == 'undefined'){
global.window = new Object();
}
Alternatively, you can use jsdom, or a similar library to create a fake DOM.
Just add the following to webpack config:
// By default, Webpack is set up to target the browser,
// not a Node environment. Try setting target in your config:
target: 'node',

Where do I put my Grunt compiled Ember.js Templates in my HTML file?

I'm working on a simple Ember.js and Express app and up to now all my templates have been in my index.html file. This is my first time using Grunt for anything much less precompile templates. (I'm using Grunt-Ember-Handlebars to tackle the compiling)
I've moved all my templates into a handlebars folder and they compile into templates.js in the same folder.
My question is this: where do I include the script tag linking to templates.js in my HTML file?
Here is how I have all my scrips laid out:
<script src="../js/jquery.js"></script>
<script src="../js/libs/handlebars-1.1.2.js"></script>
<script src="../js/libs/ember-1.3.0.js"></script>
<script src="http://builds.emberjs.com/beta/ember-data.js"></script>
<!-- APP -->
<script src="templates.js" type="text/javascript"></script>
<script src="../js/app.js"></script>
<script src='../js/router.js'></script>
<script src='../js/controllers/controllers.js'></script>
My path to my templates.js file is correct so thats not an issue. But it always returns with errors stating:
Assertion failed: Could not find "index" template or view.
The only file I know I need to include it after is my ember.js file. Other than that, it makes no difference in error output if I include it after or before any files in my App.
Thanks for the help ahead of time!
Edit:
Here is my Gruntfile:
grunt.initConfig({
ember_handlebars: {
compile: {
options: {
namespace: "emberApp.TEMPLATES"
},
files: {
"views/templates.js" : "handlebars/*.hbs"
}
}
}
});
It doesn't matter where to put them. Seems like they have wrong naming.
Put templates into templates
Name them correctly (application.hbs for application template)
Use this grunt command
ember_handlebars: {
options: {
processName: function(name) {
return name.replace(/(templates\/|\.hbs)/g, '');
}
},
files: {
"templates.js": "templates/**/*.hbs",
}

What is the matching template name for a given data-template-name

I am precompiling my templates using grunt-ember-templates. This tool is putting my templates in the Ember.TEMPLATES array, as expected. I am finetuning the configuration of grunt-ember-templates. For that I would like to know what is the expected key in the Ember.TEMPLATES array. Let's say I have this template:
<script type="text/x-handlebars" data-template-name="phones/index">
....
</script>
Currently I have this template in a file called app/templates/phones_index.hbs, and grunt-ember-templates is putting the pre-compiled template in Ember.TEMPLATES["app/templates/phones_index"], but this is wrong.
What is the expected key for data-template-name="phones/index"?
In your example the key in Ember.TEMPLATES should be "phones/index".
You can configure grunt-ember-templates to drop the first part of your path and leave everything after app/templates/ which will give you the correct key assuming you place your template inside of file app/templates/phones/index.hbs. Using this set up, the key for the app/templates/phones/index.hbs file will be Ember.TEMPLATES['phones/index'], which is the same as having an uncompiled <script> tag with data-template-name="phones/index".
Gruntfile.js (same as the Gruntfile.js in this project):
ember_templates: {
options: {
templateName: function(sourceFile) {
return sourceFile.replace(/app\/templates\//, '');
}
},
'dependencies/compiled/templates.js': ["app/templates/**/*.hbs"]
},