Running through the Concrete CMS tutorial for the flintstones theme here throws up a problem where if I place the source js and css files in a /Documents/.. development folder and the site is served by MAMP the CSS files go to the right folder but the JS files do not.
webpack.mix.js includes:
var publicDir = '/Applications/MAMP/htdocs/dlm/application/themes/flintstone';
mix.setPublicPath(publicDir);
mix
.sass('assets/scss/main.scss', 'css/main.css')
.js('assets/js/main.js', '/js/main.js');
This puts the CSS in the right place:
'/Applications/MAMP/htdocs/dlm/application/themes/flintstone/css/main.css'
But the JS files are put here:
/Applications/MAMP/dlm/htdocs/application/themes/flintstone/Applications/MAMP/htdocs/dlm/application/themes/flintstone/js/main.js
It seems the JS side cannot take a root folder redirection. Can anyone shed any light on it please?
Thanks.
Looked a bit further into webpack.mix.js and found an answer:
var publicDir = '/Applications/MAMP/htdocs/dlm/application/themes/flintstone';
mix.setPublicPath(publicDir);
mix
.webpackConfig({
output: {
filename:'js/main.js',
path: '/Applications/MAMP/htdocs/dlm/application/themes/flintstone',
},
})
.sass('assets/scss/main.scss', 'css/main.css')
.js('assets/js/main.js', 'js/main.js');
This appears to be putting both main.css and main.js into the correct folders and the Concrete theme appears to be building correctly.
As I understand it, the webpackConfig overrides the 'output' file aspect of the .js('assets/js/main.js', 'js/main.js'); line.
If I replace the webpackConfig .filename with 'js/[name].js', the destination then includes the path again creating 'js/Applications/MAMP/htdocs/dlm/application/themes/flintstone/main.js'.
Hope this helps.
I have a snowpack project with the following folder structure:
build : contains the built project
src : contains the source files
node_modules
package.json
snowpack.config.js
I set the following config:
// Snowpack Configuration File
module.exports = {
mount: {
"src": "/",
}
};
This works when I use snowpack build: the files from src are neatly placed in the build folder and I can access it using the url http://localhost/myproject/build/index.html on my computer.
Problem: when I use snowpack dev, for some reason snowpack tries to find the build folder inside the src folder ?!?
404 ERROR /Users/oldhank/Sites/basics-snowpack/src/build/_snowpack/pkg/#tensorflow/tfjs
If I remove the config file the dev works too, but then I need to have all my project files in the root directory, which looks ugly?
How can I get both the dev and build commands working with a src and build folder?
Hope this helps anyone trying to dev + build + deploy (gh-pages) Snowpack apps:
https://github.com/jgrizou/snowpack-boilerplate
Above link contains a boilerplate for Snowpack app.
Assuming I want to (my boss is making me) use webpack, and I have a file structure like:
Wherein builds is where webpack outputs the result of bundling/compiling the src folder, how do I then have index.html point to bundle.js if it is present on a server, i.e. which folder do I expose via express.static()? What is the correct "webpack" way to do this with i.e. a simple webpack.config like below? Am I missing something fundamental about how this works? Ideally I'd like to do something like the following in my index.html
<html>
<script src='bundle.js'></script>
<!-- bundle.js spits a bunch of CSS into the html, dynamically builds elements, etc -->
</html>
Or is that not how things are done in webpack?
webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
path: 'builds',
filename: 'bundle.js',
},
module: {
loaders: [
{ test: /\.css$/,
loader: "style!css"
}
]
}
};
I have tried to figure this out via the docs and this oft-linked article.
Since its a good practice to not expose any of your directory structure to end users as it creates a chance for web exploitation, nodejs with express has a mechanism to handle that. What you can do is expose this way your webpack
app.use('/buidscript', express.static(__dirname + '/builds/'));
Then, any browser requests from /buidscript/bundle.js will automatically be fetched from your builds directory.
<script src='/buidscript/bundle.js'></script>
Now you can gather your thoughts around this to make it in whatever way you would like.
For your ideal case which you are looking for
app.use(express.static(__dirname + '/builds'));
Now you can use
<script src='bundle.js'></script>
as any request bundle.js will be searched in exposed static builds directory
Add it to package.json's script
“scripts”: {
“start”: “webpack-dev-server --content-base build/ --inline --hot”,
...
}
// Use it by running
$ npm start
Now this will build your bundle.js before running index.html in development mode.
--content-base build/
will server the static files in your build folder. so then you can make use of bundle.js directly. It will look for any file changes and recompile bundle.js
Webpack docs state that output.publicPath is:
The output.path from the view of the JavaScript.
Could you please elaborate on what this actually means?
I use output.path and output.filename to specify where Webpack should output the result, but I’m not sure what to put in output.publicPath and whether it is required.
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js",
publicPath: "What should I put here?"
}
}
output.path
Local disk directory to store all your output files (Absolute path).
Example: path.join(__dirname, "build/")
Webpack will output everything into localdisk/path-to-your-project/build/
output.publicPath
Where you uploaded your bundled files. (absolute path, or relative to main HTML file)
Example: /assets/
Assumed you deployed the app at server root http://server/.
By using /assets/, the app will find webpack assets at: http://server/assets/. Under the hood, every urls that webpack encounters will be re-written to begin with "/assets/".
src="picture.jpg" Re-writes ➡ src="/assets/picture.jpg"
Accessed by: (http://server/assets/picture.jpg)
src="/img/picture.jpg" Re-writes ➡ src="/assets/img/picture.jpg"
Accessed by: (http://server/assets/img/picture.jpg)
When executed in the browser, webpack needs to know where you'll host the generated bundle. Thus it is able to request additional chunks (when using code splitting) or referenced files loaded via the file-loader or url-loader respectively.
For example: If you configure your http server to host the generated bundle under /assets/ you should write: publicPath: "/assets/"
the publicPath is just used for dev purpose, I was confused at first time I saw this config property, but it makes sense now that I've used webpack for a while
suppose you put all your js source file under src folder, and you config your webpack to build the source file to dist folder with output.path.
But you want to serve your static assets under a more meaningful location like webroot/public/assets, this time you can use out.publicPath='/webroot/public/assets', so that in your html, you can reference your js with <script src="/webroot/public/assets/bundle.js"></script>.
when you request webroot/public/assets/bundle.js the webpack-dev-server will find the js under the dist folder
Update:
thanks for Charlie Martin to correct my answer
original: the publicPath is just used for dev purpose, this is not just for dev purpose
No, this option is useful in the dev server, but its intention is for asynchronously loading script bundles in production. Say you have a very large single page application (for example Facebook). Facebook wouldn't want to serve all of its javascript every time you load the homepage, so it serves only whats needed on the homepage. Then, when you go to your profile, it loads some more javascript for that page with ajax. This option tells it where on your server to load that bundle from
filename specifies the name of file into which all your bundled code is going to get accumulated after going through build step.
path specifies the output directory where the app.js(filename) is going to get saved in the disk. If there is no output directory, webpack is going to create that directory for you.
for example:
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js"
}
}
This will create a directory myproject/examples/dist and under that directory it creates app.js, /myproject/examples/dist/app.js. After building, you can browse to myproject/examples/dist/app.js to see the bundled code
publicPath: "What should I put here?"
publicPath specifies the virtual directory in web server from where bundled file, app.js is going to get served up from. Keep in mind, the word server when using publicPath can be either webpack-dev-server or express server or other server that you can use with webpack.
for example
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js",
publicPath: path.resolve("/public/assets/js")
}
}
this configuration tells webpack to bundle all your js files into examples/dist/app.js and write into that file.
publicPath tells webpack-dev-server or express server to serve this bundled file ie examples/dist/app.js from specified virtual location in server ie /public/assets/js. So in your html file, you have to reference this file as
<script src="public/assets/js/app.js"></script>
So in summary, publicPath is like mapping between virtual directory in your server and output directory specified by output.path configuration, Whenever request for file public/assets/js/app.js comes, /examples/dist/app.js file will be served
You can use publicPath to point to the location where you want webpack-dev-server to serve its "virtual" files. The publicPath option will be the same location of the content-build option for webpack-dev-server. webpack-dev-server creates virtual files that it will use when you start it. These virtual files resemble the actual bundled files webpack creates. Basically you will want the --content-base option to point to the directory your index.html is in. Here is an example setup:
//application directory structure
/app/
/build/
/build/index.html
/webpack.config.js
//webpack.config.js
var path = require("path");
module.exports = {
...
output: {
path: path.resolve(__dirname, "build"),
publicPath: "/assets/",
filename: "bundle.js"
}
};
//index.html
<!DOCTYPE>
<html>
...
<script src="assets/bundle.js"></script>
</html>
//starting a webpack-dev-server from the command line
$ webpack-dev-server --content-base build
webpack-dev-server has created a virtual assets folder along with a virtual bundle.js file that it refers to. You can test this by going to localhost:8080/assets/bundle.js then check in your application for these files. They are only generated when you run the webpack-dev-server.
in my case,
i have a cdn,and i am going to place all my processed static files (js,imgs,fonts...) into my cdn,suppose the url is http://my.cdn.com/
so if there is a js file which is the orginal refer url in html is './js/my.js'
it should became http://my.cdn.com/js/my.js in production environment
in that case,what i need to do is just set publicpath equals http://my.cdn.com/
and webpack will automatic add that prefix
There are lots of good answers here, so I'll focus on output.publicPath: 'auto'.
Say when you build your project you get the next folder structure:
dist/blog/index.html
dist/app.js
dist/app.css
dist/index.html
In this case, both our index.html files have to have a correct path to our app.js and app.css (next - assets). Let's consider the next scenarios:
publicPath: '' or publicPath: '/':
When hosted on a server both point to the root of the website (ex. https://localhost:8080/), so everything works fine.
But should you try to open them locally, blog/index.html won't have a correct path to the assets. In case of publicPath: '' assets will be searched in the blog/ folder since that's where the relative path is pointing to. index.html still has the correct path to assets.
And in case of publicPath: '/', / points to the root of the filesystem, so neither of our index.html files will have a correct path to assets.
publicPath: 'auto':
In this case, both our index.html files will have relative paths to the assets. So, blog/index.html will be pointing to ../app.css, and index.html will be pointing to app.css.
The webpack2 documentation explains this in a much cleaner way:
https://webpack.js.org/guides/public-path/#use-cases
webpack has a highly useful configuration that let you specify the base path for all the assets on your application. It's called publicPath.
publicPath is used by webpack for the replacing relative path defined in your css for refering image and font file.
I am trying to use the r.js optimizer to build all of my dependencies into a single file. Here is my file structure:
app
bin
src
css
main.css
js
libs
raphael-2.1.0
eve.js
raphael.amd.js
raphael.core.js
raphael.svg.js
raphael.vml.js
jquery-1.8.0.js
require-2.0.5.js
main.js
build.js
index.html
r.js
Here are the contents of build.js:
({
baseURL: 'js',
dir: '../bin',
paths: {
'jquery': 'libs/jquery-1.8.0',
'raphael': 'libs/raphael-2.1.0/raphael.amd'
},
name: 'main',
removeCombined: true
})
The 'libs/raphael-2.1.0/raphael.amd' dependency loads everything else in the raphael-2.1.0 directory. The app works as expected if I visit app.local/src, it loads the modules at runtime via require with a single script tag in my index.html file like this:
<script src="js/libs/require-2.0.5.js" data-main="js/main.js" type="text/javascript" charset="utf-8"></script>
However, if I try to run the command node r.js -o src/build.js from app, I get an error like:
Error: ERROR: module path does not exist: /app/src/main.js for module named: main. Path is relative to: /app
at /app/r.js:14215:31
... and everything gets copied into bin "as is". If I add 'main': 'js/main' to the paths object, then r.js can't find jquery and raphael, if I ad js/ to the jquery and raphael paths then libs/raphael-2.1.0/rapheal.amd's dependency declarations are wrong. If I update those, then everything builds as expected, but now the app at app.local/src/index.html is broken. Also, I thought that was the point of having a baseURL property in the build file no? It looks to me like baseURL is being ignored. What am I doing wrong?
As most things in JavaScript, the baseUrl setting is case sensitive. Change URL to Url and see if it helps.