I have a Django + React project running at localHost:8000.
VIEWS.PY
def index(request):
return render(request, 'frontend/index.html')
INDEX.HTML
{% load static %}
<script src="{% static "frontend/main.js" %}"></script>
When user click a button in main.js file, it request for 0.bundle.js to server, but server fails to serve it.
I can't do loading manually (<script src="{% static "frontend/0.main.js" %}"></script> This scripts load the 0.bundle.js but I want dynamic import).
As you can see in attached image, the frontend JS file requesting file at rootLocalhost.
Any ideas or directions will be appreciated .
configured webpack as below,new chunk files will point to Django static files
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
loader: ["style-loader", "css-loader"],
},
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
],
},
output: {
chunkFilename: "static/frontend/[name].bundle.js",
},
};
Related
I am currently using laravel-mix, Django, and Vue together. I would like to load the static image inside the Vue component. My images store in static/img folder
First of all, I have set up an alias in Webpack config pointing to the static folder.
const path = require('path')
let publicPath = 'src/static'
module.exports = {
resolve: {
extensions: ['.js', '.vue'],
alias: {
'#': path.join(__dirname, publicPath)
},
},
}
And load the image in Vue component
<img :src='require(`#/img/Blue.jpg`).default' alt="">
I can't load images and Webpack generated new images into the images folder. How to prevent it and load image correct
change this from
<img :src='require(`#/img/Blue.jpg`).default' alt="">
To:
<img :src="require('#/img/Blue.jpg')" alt="">
hope this may be help u
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
I'm working on Django-react project and having issue with rendering React component on Django server. To be precise, React always render me the same content even if I change it. I'm using Webpack, Babel-loader and running it on localhost.
project/templet/frontend/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Django-React</title>
</head>
<body>
<div id="app" class="columns"><!-- React --></div>
{% load static %}
<script type='text/javascript' src="{% static "frontend/main.js" %}"></script>
</body>
</html>
Entry point:
import ReactDOM from "react-dom";
import App from './components/App';
ReactDOM.render(<App/>, document.getElementById("app"));
Scripts in package.json:
"scripts": {
"dev": "webpack --mode development ./frontend/src/index.js --watch ./frontend/static/frontend/main.js",
"build": "webpack --mode production ./frontend/src/index.js --output ./frontend/static/frontend/main.js"
}
Babel config:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
};
So, when I write some content in App component (eg. render div with "test") I can see it in my browser, but when I want to change it, and after refresing page, get the same content from div tag
From what i can understand from your question, When you first render a div with 'test' in it, it renders, but after that, further changes dont update.
Its because the javascript is not being updated on Django and you need to use collectstatic to sync the builds which is not very efficient.
The way to go is to use django-webpack-loader and webpack-bundle-tracker.
install webpack-bundle-tracker
npm install --save-dev webpack-bundle-tracker
install django-webpack-loader:
pip install django-webpack-loader
django-webpack-loader is a python package which injects link and script tag for the bundles which webpack generates dynamically.
webpack-bundle-tracker plugin emits necessary information about webpack compilation process to a json file so django-webpack-loader can consume it.
For webpack to track changes made in your App, You need to create a server that monitors changes in your React app and bundle your JS.
Note: We make use of a node server.
// Webpack Server
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const config = require('./webpack.server.config');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
inline: true,
historyApiFallback: true
}).listen(3000, '0.0.0.0', function (err, result) {
if (err) {
console.log(err)
}
console.log('Listening at 0.0.0.0:3000')
});
The config files used by webpack.server.js would be at webpack.server.config.js
// webpack.server.config.js
const path = require("path");
const BundleTracker = require('webpack-bundle-tracker');
module.exports = {
mode: 'development',
entry: {
main: './frontend/src/index.js',
devServer: 'webpack-dev-server/client?http://localhost:3000'
},
output: {
filename: "[name].js",
path: path.resolve('./frontend/static/frontend/bundles/'),
publicPath: 'http://localhost:3000/frontend/static/frontend/bundles/', // django-webpack-loader overrides django's STATIC_URL with this path
},
plugins: [
new BundleTracker({filename: './frontend/webpack-stats.json'}), // Pass the correct path to the WEBPACK_LOADER in django settings
],
devServer: {
contentBase: './frontend/static/frontend/bundles/',
},
};
Note that the server will by default keep the bundles in memory and
not write to disk
When the server is stopped, there would be no sign of the bundled files as they were not compiled to memory.
To build your files to memory in development, create another config file at webpack.dev.config.js
// webpack.dev.config.js
const path = require("path");
const BundleTracker = require('webpack-bundle-tracker');
module.exports = {
mode: 'development',
entry: {
main: './frontend/src/index.js',
},
output: {
filename: "[name].js",
path: path.resolve('./frontend/static/frontend/bundles/'),
},
plugins: [
new BundleTracker({filename: './frontend/webpack-stats.json'}), // Pass the correct path to the WEBPACK_LOADER in django settings
],
};
While to build your files for Production, create another config file at webpack.prod.config.js
// webpack.prod.config.js
const path = require("path");
const BundleTracker = require('webpack-bundle-tracker');
module.exports = {
mode: 'production',
entry: {
main: './frontend/src/index.js',
},
output: {
filename: "[name].js",
path: path.resolve('./frontend/static/frontend/dist/'),
},
plugins: [
new BundleTracker({filename: './frontend/webpack-stats-prod.json'}), // Pass the correct path to the WEBPACK_LOADER in django settings
],
};
In your Django settings;
import sys
import os
# Assuming this is your base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Also assuming this is your base directory
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
# In development
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'bundles/',
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'), # Path to 'webpack-stats.json'
}
}
# In production
if not DEBUG:
WEBPACK_LOADER['DEFAULT'].update({
'BUNDLE_DIR_NAME': 'dist/',
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-prod.json') # Path to 'webpack-stats-prod.json'
})
INSTALLED_APPS = (
...
'webpack_loader',
)
Your index.html should look like this now;
{% load render_bundle from webpack_loader %} <<< Add this.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Django-React</title>
</head>
<body>
<div id="app" class="columns">
<!-- React -->
</div>
{% render_bundle 'main' %} <<< Add this.
</body>
</html>
Now, Your package.json should look like this;
"scripts": {
"dev": "node ./webpack.server.js",
"build-dev": "webpack --mode development --config ./webpack.dev.config.js",
"build-prod": "webpack --mode production --config ./webpack.prod.config.js"
}
So, To develop with automatic bundling, just run:
npm run dev
To build your files to memory after the webpack server is stopped, just run:
npm run build-dev
And finally, to build with production optimizations, just run:
npm run build-prod
I tried to modify to your project, feel to adjust according to your project structure. Check the below referrences to guide you better. They helped me out!
References:
Let's modernize the way we handle frontend code with Django
Using Webpack transparently with Django + hot reloading React components as a bonus
Modern Django: Part 1: Setting up Django and React
The application runs fine in development, but once in production the generated webpack bundle file is serving the contents of index.html and not all the bundled modules and dependencies.
Whenever I check the bundle file on the server, everything seems alright, but the same path is served differently on the client.
webpack.config.js
//require our dependencies
var path = require('path')
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
module.exports = {
//the base directory (absolute path) for resolving the entry option
context: __dirname,
//the entry point we created earlier. Note that './' means
//your current directory. You don't have to specify the extension now,
//because you will specify extensions later in the `resolve` section
entry: [
'./assets/js/index'
],
output: {
path: path.resolve('./assets/bundles/'),
filename: "[name]-[hash].js"
},
plugins: [
//tells webpack where to store data about your bundles.
new webpack.NoErrorsPlugin(), // don't reload if there is an error
new BundleTracker({filename: './webpack-stats.json'}),
//makes jQuery available in every module
new webpack.ProvidePlugin({
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
],
module: {
loaders: [
// we pass the output from babel loader to react-hot loader
{
test: [/\.js$/, /\.es6$/, /\.jsx?$/],
exclude: /node_modules/,
loaders: ['babel'],
},
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
},
resolve: {
//tells webpack where to look for modules
modulesDirectories: ['node_modules'],
//extensions that should be used to resolve modules
extensions: ['', '.js', '.jsx']
}
}
Served Content:
Uncaught SyntaxError: Unexpected token <
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!--<title></title>-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="/static/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="/static/materialize-css/dist/js/materialize.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/javascript" src="/static/assets/bundles/main-210eb139915d8d6abedf.js" ></script>
</body>
Thanks in advance.
I can't get my jasmine unit-tests to load the a component for testing.
Webstorm is telling me that everything is good to go in terms of syntax. But when I load live-server to have the unit test load it doesn't seem to work.
I have it compiling to a test directory at root.
So here is my directory tree (abv for the ease):
-- client(src)
|-- common
|---- welcome.component.ts
|---- welcome.spec.ts
-- node_modules
-- tests(compiled spec and components)
|-- client(src)
|---- common
|------ welcome.component.ts
|------ welcome.spec.ts
--unit-tests.html
--systemjs.config.js
live server is giving me this:
GET /tests/client/common/welcome.component 404
welcome.spec.ts
/// <reference path="../../typings/main/ambient/jasmine/index.d.ts" />
import {WelcomeComponent} from './welcome.component';
describe('Welcome tests', () => {
let welcome:WelcomeComponent;
beforeEach(() => {
welcome = new WelcomeComponent('sir');
});
it('Nombre should equal sir', () => {
expect(welcome.nombre).toEqual('sir');
})
});
unit-tests.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>Tests</title>
<link rel="stylesheet" href="node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
</head>
<body>
<!-- #1. add the system.js library -->
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
// #2. Configure systemjs to use the .js extension
// for imports from the app folder
System.config({
packages: {
'client': {defaultExtension: 'js'}
}
});
// #3. Import the spec file explicitly
System.import('tests/client/common/welcome.spec.js');
System.import('tests/client/common/header.spec.js')
// #4. wait for all imports to load ...
// then re-execute `window.onload` which
// triggers the Jasmine test-runner start
// or explain what went wrong.
.then(window.onload)
.catch(console.error.bind(console));
</script>
</body>
</html>
systemjs.config.js
(function(global) {
// map tells the System loader where to look for things
var map = {
'app': 'tests/client', // 'dist',
'rxjs': 'node_modules/rxjs',
'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
'#angular': 'node_modules/#angular'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { defaultExtension: 'js' },
};
var packageNames = [
'#angular/common',
'#angular/compiler',
'#angular/core',
'#angular/http',
'#angular/platform-browser',
'#angular/platform-browser-dynamic',
'#angular/router',
'#angular/router-deprecated',
'#angular/testing',
'#angular/upgrade',
];
// add package entries for angular packages in the form '#angular/common': { main: 'index.js', defaultExtension: 'js' }
packageNames.forEach(function(pkgName) {
packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});
var config = {
map: map,
packages: packages
}
// filterSystemConfig - index.html's chance to modify config before we register it.
if (global.filterSystemConfig) { global.filterSystemConfig(config); }
System.config(config);
})(this);
I can add more if you need me too, the header.spec works great, but it's self-container. (expect true = true, etc)
SystemJS should be loading this for the unit-tests but it does not, the site itself works great so the Welcome.component is fine. But for some reason I cannot load the unit test.
Where would I be going wrong? I feel like this is a config issue, but I am not very familiar with unit-tests.
I had a similar issue the other day, take a look at this comment. If you have a spec-bundle.js or something similar, make sure var testing and var browser is referring to RC1 and not beta.
Also, if you have this somewhere: testing.setBaseTestProviders(
browser.TEST_BROWSER_STATIC_PLATFORM_PROVIDERS,
browser.TEST_BROWSER_STATIC_APPLICATION_PROVIDERS);
this is how it should look for RC1, it was different for beta