I am creating a React application, I used npm eject so I could get to the Webpack config. I want to change the paths to assets so they don't have the leading slash. This is because when I run my application I copy the files over to a Ratpack server, so when the path is /assets/js/main.js it points to my route rather than my assets folder.
So my current webpack config is
output: {
// The build folder.
path: paths.appBuild,
// Generated JS file names (with nested folders).
// There will be one main bundle, and one file per asynchronous chunk.
// We don't currently advertise code splitting but Webpack supports it.
filename: 'assets/static/js/[name].[chunkhash:8].js',
chunkFilename: 'assets/static/js/[name].[chunkhash:8].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath: publicPath
},
However it always adds on the leading slash.
Like so
<script type="text/javascript" src="/assets/static/js/main.4d5cbecd.js">
Is there a way to have it so it builds like
<script type="text/javascript" src="assets/static/js/main.4d5cbecd.js">
Assuming you are talking about create-react-app's config, you could remove the line publicPath: publicPath, and it will generate it without leading slash.
However, I think your server should serve files too, when they are requested specifically, instead of redirecting to index page. If that's what's happening.
Another advice is for production, use production build instead of development build.
Related
I’m experiencing problems deploying a Vue JS app built using the Webpack CLi to work.
If uploaded in a root directory everything renders fine, but inside a subfolder, all the links break.
I want deploy VueJS App to this url :
https://event.domain.net/webinar
I have added publicPath in vue.config.js :
var path = require(‘path’)
module.exports = {
publicPath: ‘./’
}
But only the css and js folders point to the path /webinar.
For assets, fonts and others still point to the subdomain https://event.domain.net.
CSS and JS point to path /webinar
Asset, fonts still point to subdomain https://event.domain.net/
Console
use value of publicPath as /webinar that should work.
More details are here https://cli.vuejs.org/config/#publicpath
you can configure publicPath even based on environment.
Sagar Rabadiya pointed you to the right link:
create a file called vue.config.js in the project root (where your package.json is located).
prompt the following code snippet inside:
module.exports = {
publicPath: process.env.NODE_ENV === 'production'? '/your-sub-directory/' : '/'
}
and save the file.
Open a terminal and navigate to your project, then run npm run build to generate a production build from it.
As soon as the production build has been generated, copy the contents from it and paste it in the sub-directory you created in the root folder. For example, if you use Apache, the default root directory is the htdocs folder. I've also created a virtual host on the server, maybe you also need to do this.
Open the browser and type the address where your sub-directory lives. For example: http://your-server-url:your-port/your-sub-directory/ Your should see your app now.
Hello I've got an issue with a Nuxt.js app that I can't seem to resolve. What I want to do is to change the name of the generated _nuxt folder with some other name. So far I've updated the nuxt.config.js and added this snippet:
build: {
publicPath: '/new-folder'
},
as far as I understand this publicPath variable expects a CDN link so probably this is not the correct way of changing the default _nuxt folder name.
I have also tried adding the buildDir: 'new-folder but when I run the build command it doesn't show up in the project. No matter what changes I added in the nuxt.config file when I deployed it on heroku all the assets where still in the _nuxt folder which causes issues to my project. Am I not seeing something am I doing something wrong?
Since the default answer in nuxt JS Documentation is /_nuxt/. The correct answer should be /yourCustomName/ - be ware that you need two forward slash.
In nuxt.config.js
build: {
publicPath: '/customName/'
}
t's simple, just change in build the publicPath.
buildDir is to change the folder for development, where the files will be when coding
nuxt.config.js:
build: {
publicPath: 'new-folder/',
},
in my case, my publicPath is leo/
you can check more about it here:
https://medium.com/#andrejsabrickis/how-to-set-custom-configuration-for-nuxt-js-generate-task-5055e53c2da5
Architecture
I would like to share code between client and server side. I have defined aliases in the webpack config:
resolve: {
// Absolute paths: https://github.com/webpack/webpack/issues/109
alias: {
server : absPath('/src/server/'),
app : absPath('/src/app/'),
client : absPath('/src/client/'),
}
},
Problem
Now on the server side I need to include webpack in order to recognize the correct paths when I require a file. For example
require('app/somefile.js')
will fail in pure node.js because can't find the app folder.
What I need (read the What I need updated section)
I need to be able to use the webpack aliases. I was thinking about making a bundle of all the server part without any file from node_modules. In this way when the server starts it will use node_modules from the node_modules folder instead of a minified js file (Why? 1st: it doesn't work. 2nd: is bad, because node_modules are compiled based on platform. So I don't want my win files to go on a unix server).
Output:
Compiled server.js file without any node_modules included.
Let the server.js to use node_modules;
What I need updated
As I've noticed in https://github.com/webpack/webpack/issues/135 making a bundled server.js will mess up with all the io operation file paths.
A better idea would be to leave node.js server files as they are, but replace the require method provided with a custom webpack require which takes in account configurations such as aliases (others?)... Can be done how require.js has done to run on node.js server.
What I've tried
By adding this plugin in webpack
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"ignore", /* filename= */"server.bundle.js")
Entries:
entry: {
client: "./src/client/index.js",
server: "./src/server/index.js",
ignore: ['the_only_node_module'] // But I need to do that for every node_module
},
It will create a file server.js which only contains my server code. Then creates a server.bundle.js which is not used. But the problem is that webpack includes the webpackJsonp function in the server.bundle.js file. Therefore both the client and server will not work.
It should be a way to just disable node_modules on one entry.
What I've tried # 2
I've managed to exclude the path, but requires doesn't work because are already minified. So the source looks like require(3) instead of require('my-module'). Each require string has been converted to an integer so it doesn't work.
In order to work I also need to patch the require function that webpack exports to add the node.js native require function (this is easy manually, but should be done automatically).
What I've tried # 3
In the webpack configuration:
{target: "node"}
This only adds an exports variable (not sure about what else it does because I've diffed the output).
What I've tried # 4 (almost there)
Using
require.ensure('my_module')
and then replacing all occurrences of r(2).ensure with require. I don't know if the r(2) part is always the same and because of this might not be automated.
Solved
Thanks to ColCh for enlighten me on how to do here.
require = require('enhanced-require')(module, require('../../webpack.config'));
By changing the require method in node.js it will make node.js to pass all requires trough the webpack require function which allow us to use aliases and other gifts! Thanks ColCh!
Related
https://www.bountysource.com/issues/1660629-what-s-the-right-way-to-use-webpack-specific-functionality-in-node-js
https://github.com/webpack/webpack/issues/135
http://webpack.github.io/docs/configuration.html#target
https://github.com/webpack/webpack/issues/458
How to simultaneously create both 'web' and 'node' versions of a bundle with Webpack?
http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/
Thanks
Thanks to ColCh for enlighten me on how to do here.
require = require('enhanced-require')(module, require('../../webpack.config'));
By changing the require method in node.js it will make node.js to pass all requires trough the webpack require function which allow us to use aliases and other gifts! Thanks ColCh!
My solution was:
{
// make sure that webpack will externalize
// modules using Node's module API (CommonJS 2)
output: { ...output, libraryTarget: 'commonjs2' },
// externalize all require() calls to non-relative modules.
// Unless you do something funky, every time you import a module
// from node_modules, it should match the regex below
externals: /^[a-z0-9-]/,
// Optional: use this if you want to be able to require() the
// server bundles from Node.js later
target: 'node'
}
This is a config file in the /themes/ifd/js/ folder:
require.config({
// Initialize the application with the main application file
deps: ['plugins/console', 'main'],
baseUrl: '/themes/ifd/js/components'
paths: {
jquery: 'jquery/jquery.min',
flexslider: 'flexslider/jquery.flexslider-min',
easydropdown: 'easydropdown/jquery.easydropdown.min',
bpopup: 'bpopup/jquery.bpopup.min',
jqrangeslider: 'jqrangeslider/jQRangeSlider',
jqueryui: 'jquery-ui/js/jquery-ui-1.10.4.custom.min'
// More additional paths here
},
shim: {
jqueryui: 'jquery'
},
// Prevent caching issues, by adding an additional URL argument
urlArgs: 'bust=' + (new Date()).getDate()
});
I've got a main.js file in the /themes/ifd/js folder too:
require([
// Require the modules
'modules/module',
'jquery',
'flexslider',
'easydropdown',
'bpopup',
'jqueryui',
'jqrangeslider'
], function (module) {
'use strict';
// Rest of a file
And rest of files (modules?) are inside /themes/ifd/js/components:
Screenshot of list of files
In my HTML I have:
<script data-main="/themes/ifd/js/main" src="/themes/ifd/js/requirejs.js"></script>
The messages I see in Chrome console:
GET http://DOMAIN/themes/ifd/js/jquery.js 404 (Not Found) requirejs.js:34
GET http://DOMAIN/themes/ifd/js/flexslider.js 404 (Not Found)
I can't find what is wrong and why it doesn't search in components directory...
The entry point for requirejs is the main module specified in the html file.
<script data-main="/themes/ifd/js/main" src="/themes/ifd/js/requirejs.js"></script>
requirejs loads '/themes/ifd/js/main.js' 1st. Now in the main.js file, require([...]) try to load in the module specified in the args but requirejs won't be able to find them.
The reason is that requirejs does not know about them since require.config (...) is not executed.
Need to have 'require.config (...)' in '/themes/ifd/js/main.js' to do all the settings
Here is a working example. It includes Requirejs, jQueryMobile, Backbone, and Marinonette.
In the index.html file, you need to specify the main module for requirejs to load.
<script type="text/javascript" data-main="js/main" src="js/libs/require-2.1.2.min.js"></script>
In this example, the main module is under "js/main.js"
Inside, main.js, you specify the require.config and use define to load your modules.
The network activity you show us indicates that your configuration is completely ignored by RequireJS. And you say "Then i have that in my html":
<script data-main="/themes/ifd/js/main" src="/themes/ifd/js/requirejs.js"></script>
You've shown the contents of /themes/ifd/js/main.js but it does not include your configuration, which apparently is in a different file.
The solution here would be to move your call to require.config into your main.js file, before your call to require.
It looks like you're just loading main.js and never telling RequireJS to use your config.
This RequireJS issue lists several ways to load both a config and a main -
put the config on the HTML before you require the top-level module.
load the config.js with another tag.
do a nested require() on the HTML file (require config than require your main).
do a nested require() inside main.js.
keep the configuration inside main.js
The best approach will vary based on your project structure, I've been doing 5 way more often than the others since I usually have a single entry-point for all pages, but in some cases I used 1 and 2.
Further down the page some code examples of these approaches are also shown.
Having a lot of trouble understand how paths are treated at various points in the configuration and usage of grunt-usemin.
I've got the following repo layout, where the repo root will also be the web app root:
/dashboard/index.html
/Gruntfile.js
/vendor/...some 3rd party CSS and JS...
So the index.html file -> somedomain.com/dashboard/index.html.
The index.html file includes some CSS and JS assets from the /vendor folder. I have grunt configured to put build output in a build folder:
/build/dashboard/index.html
In the index.html file, I have usemin blocks wrapped around all the CSS link and JS script tags:
<!-- build:css(.) app.min.css -->
<!-- build:js(.) app.min.js -->
I had to specify an "alternative search path" with "(.)" so that a script tag for "/vendor/backbone.js" will find it in the right place. Until I did that, it was looking for /dashboard/vendor/backbone.js.
I want the output of processing the CSS/JS assets to be output to build/dashboard/app.min.css and build/dashboard/app.min.js, and included by index.html using a simple relative "app.min.css/js" path.
The problem is, grunt-usemin seems to be using the "app.min.*" path I'm specifying for both contexts in a way that makes it impossible for them to work together:
1) It treats the path as relative to the build directory for purposes of creating the file; the files end up in build/app.min.css and build/app.min.js.
2) It treats the path as relative to the index.html file for purposes of generating the new link/script tags; the browser loads build/dashboard/index.html, which then tries to load "app.min.css", which maps to build/dashboard/app.min.css.
Is there a solution?
I'm really late to the party, but I was also extremely frustrated by this issue and didn't find any satisfying fixes or work arounds. So I worked out some pretty dirty tricks to hopefully better work around this issue. So I'd like to share it with you.
First of all, let's quickly review why this issue happens. When usemin generates output JS/CSS files, it performs a simple path join between your dest directory and the output directory you specified in your usemin block. So if dest is build and usemin block is
<!-- build:css(.) app.min.css -->
then it joins build with app.min.css to spit out the output file at build/app.min.css
But then the usemin task simply replaces the path in your block to you end up with
<link rel="stylesheet" href="app.min.css"/>
which is now linking the wrong directory since your HTML file is under build/dashboard/index.html
So my work around revolves around this idea: what if dest directory is relative to where the HTML file is located? Wouldn't that solve this issue? So given the above example, what if dest is build/dashboard? You can see that it will spit out the output file location and link it correctly. Keep in mind that you are supposed to create a copy task to copy over your HTML files, so make sure your HTML file is copied to build/dashboard/index.html as before.
Of course, the next question would be what if I have HTML files in multiple directories? Wouldn't that be super painful and unintuitive to create a useminPrepare target for each directory, where HTML files could reside? This is why I create a very special grunt task just for working around this issue while I was creating my own grunt scaffolding. I call it useminPreparePrepare Yes, it's deliberately named stupidly, because I'm hoping to remove this thing altogether one day when usemin people make an actual fix for this issue.
As its name suggests, this is a task to prepare useminPrepare configs. It does exactly what I described above. All of its configs mirror useminPrepare configs (in fact, most of them are simply copied over to useminPrepare), with one exception: you need to specify a src directory to identify the root directory of all of your sources so that it can generate relative path to the HTML files. So in your example src: "." will be fine. To use useminPreparePrepare, import it into your build first (you may want to just copy and paste my code, I don't mind), rename your useminPrepare task to useminPreparePrepare and add src property that I just mentioned. Make sure you run useminPreparePrepare with whatever target you like, then immediately run useminPrepare without specifying target so that all of its targets are run. This is because useminPreparePrepare will generate one target for each directory relative to where HTML files are found and copies over your configs for the useminPreparePrepare target your ran. This way, your config can simply look for all HTML files.
Example
"useminPreparePrepare": {
// Search for HTML files under dashboard even though src is .
// because we want to avoid including files generated under build directory.
html: "dashboard/**/*.html",
options: {
src: ".",
dest: "build",
...
"usemin": {
html: ["build/**/*.html"],
...
"copy": {
html: {
files: [{
expand: true,
src: ["dashboard/**/*.html"],
dest: "build"
}
]
},
...
Hope this helps! Have a good day.
EDIT: I realized that given the above example, if you actually include all HTML files from current directory, you will include the generated HTML files too if they are not cleaned ahead of time. So either you clean them ahead of them or look under dashboard directory. I'd recommend separating src and dest directories so that config could look a lot more intuitively.
I don't like it, but the only way I've found to make it work so far is to specify a full path:
<!-- build:css(.) /dashboard/app.min.css -->
<!-- build:js(.) /dashboard/app.min.js -->
The leads to the app* files being in /build/dashboard alongside index.html (which is where I want them), and index.html ends up with the following tags:
<link rel="stylesheet" href="/dashboard/app.min.css">
<script src="/dashboard/app.min.js"></script>
It means the dashboard app is now acutely aware of it's location within the whole, so you can't just rename or relocate it's position in the tree without updating those paths.