I have built a custom HTML framework that has a pretty simple project structure. I really need to grab from 3 separate directories views,js, and components. I am very new to webpack but I figured with its configurability there would be a way for me to have all of these imports importing something like /components/random_component_name.js I need webpack to resolve these files to be their private path.
I have tried many different things this is what I have most recently tested
const path = require('path');
module.exports = {
entry: path.resolve(__dirname + '/public/js/main.js'),
module: {
generator: {
js: {
// Generator options for asset modules
// Customize publicPath for asset modules, available since webpack 5.28.0
publicPath: '/js',
// Emit the asset in the specified folder relative to 'output.path', available since webpack 5.67.0
outputPath: path.resolve(__dirname + 'public/js'),
},
},
},
}
How can i get this functionality out of webpack. Surely it shouldn't be too hard. I am new to all bundlers like this so sorry if this is horribly wrong.
I finally figured it out. I had tried a method close to this before but neglected the '/' in the alias key names so now this work
const path = require('path');
module.exports = {
//...
entry: {
main: './src/js/main.js',
},
resolve: {
alias: {
'/components': path.resolve(__dirname, 'src/components/'),
'/js': path.resolve(__dirname, 'src/js/'),
'/views': path.resolve(__dirname, 'src/views/'),
},
}
};
Related
For my firebase application I need some backend functions that would load i18n files and send them to client. I am able to use webpack to bundle the files for deploying. That works fine. But what I would also like to do is to change the content of the files (because phrases in the app may be added or deleted), which is not possible in this case. Is there a way to upload these files along with the scripts?
There is this section in the firebase documentation: https://firebase.google.com/docs/functions/handle-dependencies. However, I wouldn't really like to write "language_namespace": "file:locales/language/namespace.json" for each file I have.
I didn't find any easy workaround and I will probably use some other system for the i18n, because this one is overcomplicated and it will not be easy to work with. Anyway, here is the solution in case someone faces a similar problem:
I used webpack-cli instead of tsc to bundle my files. Here is what my folder structure looked like:
root
- functions
- webpack.config.js
- lib
- src
- index.ts // File with the function
- ...
- public
- locales // Locales folder I needed to be uploaded
- en
- ...
- ru
- ...
- ...
- ...
- ...
It seems like firebase will upload anything that it finds in the lib folder, so when bundling the functions, I just used copy-webpack-plugin to copy locales there. Here is what my webpack config looked like:
const path = require('path')
const nodeExternals = require('webpack-node-externals')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'lib'),
libraryTarget: 'this',
filename: 'index.js',
},
mode: 'development',
resolve: {
extensions: ['.ts', '.tsx', '.js'],
},
target: 'node',
externals: [nodeExternals()],
module: {
rules: [
{ test: /\.tsx?/, loader: 'ts-loader', options: { transpileOnly: true } },
]
},
plugins: [
new CopyWebpackPlugin([{
from: path.resolve(__dirname, '../public/locales'),
to: './locales'
}])
]
}
Then, to prevent webpack from changing normal require to __webpack_require__whatever, I had to use the __non_webpack_require__ function, that would then be transpiled to normal require and let me read copied files from lib/locales:
// In case you are using typescript and want to prevent the compiler
// from arguing that `__non_webpack_require__` is not defined
declare function __non_webpack_require__(module: string): any
export const getLocale = functions.https.onRequest((req, res) => {
const { language, namespace } = req.query
try {
const translation = __non_webpack_require__(`./locales/${language}/${namespace}.json`)
// do stuff
res.send(translation)
} catch(e) {
if(e.code === 'MODULE_NOT_FOUND') {
res.status(400).end("Couldn't find translation for ${language}/${namespace}")
} else { /* ... */ }
}
})
After doing this, both firebase emulators:start --only functions and firebase deploy --only functions:getLocale worked correctly
There are a lot of questions on this, and a lot of answers, read below to see what I've tried, and how they didn't work. I assume my problem is coming from a fundamental misunderstanding of how url-loader works.
I have images included like this in my .less files. I am using two different formats as an example of what I've tried.
app.less
#logo {
background-image: url("~/img/LoginMarketingImage.png");
}
#logotwo{
background-image: url("../public/img/LoginMarketingImage2.png");
}
webpack.config.js
module.exports = {
context: path.resolve(__dirname, '../../'),
entry: {
app: './public/js/app.js'
},
output: {
path: path.resolve(__dirname, '../build'),
filename: '[name].js',
publicPath: '/'
},
I have also tried
webpack.config.js
module.exports = {
context: path.resolve(__dirname, '../../'),
entry: {
app: './public/js/app.js'
},
output: {
path: path.resolve(__dirname, '../build'),
filename: '[name].js',
publicPath: ''
},
As well as below, based on: webpack css-loader not finding images within url() reference in an external stylesheet
webpack.config.js
module.exports = {
context: path.resolve(__dirname, '../../'),
entry: {
app: './public/js/app.js'
},
output: {
path: path.resolve(__dirname, '../build'),
filename: '[name].js',
publicPath: 'https://localhost:9081/'
},
My module config looks like
webpack.config.js
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 2000000,
name: utils.assetsPath('img/[name].[ext]')
}
},
]
}
I have experimented with a limit of 1 and a higher limit, to see if inline vs non-inlined works.
My folder structure is as follows
build/
less/
app.less
public/
img/
LoginMarketingImage.png
LoginMarketingImage2.png
config/
webpack/
webpack.config.js
My Results
If I set the limit to 1, and force all images to be output directly, the only time they are output is if they use the url("../") syntax. url("~/") throw no webpack errors, but the images don't get output to the build folder. In this case, the images using url("../") syntax throw no errors in the browser either. However, this is not ideal, as I want to take advantage of url-loader's ability to return a DataURL. In this scenario, images using url("~/") syntax give the error GET https://localhost:9081/img/logo.png 404 (Not Found), regardless of publicPath setting.
If I set the limit to 20000000, obviously no images are put in the build folder by file-loader. However, all images return a 404 in the browser, regardless of publicPath setting.
I feel like I'm misunderstanding how to use url-loader. What kind of configuration do I need, and how should I be requiring my files inside less, to take advantage of url-loader's ability to return DataURLs?
EDIT: Based on this issue, I have ensured that css sourcemaps are disabled.
I can't pinpoint the problem here, but it seems like the publicPath config is the problem. I threw together a sample gist with the minimium you need to get the url-loader working properly.
Some things to note:
Make sure the test option is correct
You didn't mentioned which version of webpack you're using, but I assume it's > 2. If it's == 2 then you should upgrade because the newer versions fixed a lot of bugs and the config API is almost 100% compatible
Do not use the tilde import path, it's a shortcut to project-root-dir/node_modules (at least in webpack 1.x)
I assume you're using webpack-dev-server. If not, then you should not need to set the publicPath and such
Do not change url-loader's name option unless you got everything working without it. Changing it's path can confuse webpack
I am currently trying to load a variable array of modules with Webpack.
I've found this link: webpack can not require variable ,the request of a dependency is an expression but it doesn't seem to work for me.
In my project I've got a module inside my node_modules folder. The entry point of the module is called index.js.
Here's the basic structure:
| app
+---app.js
| js
+---gen.js
| node_modules
+---sample_module_1
| +---index.js
+-sample-module_2
+---index.js
| webpack.config.js
In future I'd like to add new modules. Therefore I tried following approach:
//app.js
var modules = [
"sample_module_1",
"sample_module_2"
]
for(var i = 0; i < modules.length; i++) {
require(modules[i] + "/index.js");
}
But Webpack doesn't seem to find the module. I've tried adding a resolveLoader to the webpack.config.js file:
//webpack.config.js
var path = require('path');
module.exports = {
entry: './app/app.js',
output: {
filename: 'gen.js',
path: path.resolve(__dirname, 'js')
},
resolveLoader: {
modules: ["node_modules"],
extensions: ['*', '.js']
}
};
Still, Webpack is not able to find the module.
I've also tried the suggestions on https://webpack.github.io/docs/context.html but still no results.
Any suggestions?
Im trying to export these two pieces of code cli.js and program.js, where cli depends on program and program has a bunch of other dependencies...
Webpack is doing a great job in bundling all dependencies of program.js (./a,./b,./c...) and correctly ignoring the ones that are externals like 'jquery', 'bluebird' ...
however when it comes to bundle the cli.js .. its not referencing the program.dist.js entry point, but bundling a copy of the entire program once again...
how could i fix this issue? is it a limitation with webpack? or is there any way around it? im currently using webpack 2.1.0-beta.27
this is my webpack.config.js
const path = require('path');
module.exports = {
entry: {
cli: './bin/cli.js',
program: './program.js',
},
target: 'node',
output: {
libraryTarget: 'umd',
filename: '[name].dist.js',
umdNamedDefine: true,
path: path.resolve(__dirname, 'distribution'),
},
externals: [
/^[a-z\-0-9]+$/
]
}
program.js
let a = require('./a'),
b = require('./b'),
c = require('./c');
bin/cli.js
const program = require('../program');
program.doSomething();
just a side node...
I cant split it into chunks with CommonsChunkPlugin because it would make my cli.dist.js unable to be executed by node.js like node cli.dist.js
With Webpack, there is support for code splitting to different bundles. One of the options is to specify a set of modules you would like to choose as a split point.
Taken from here:
var webpack = require("webpack");
module.exports = {
entry: {
app: "./app.js",
vendor: ["jquery", "underscore", ...],
},
output: {
filename: "bundle.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.bundle.js")
]
};
This shows how to split out modules like jquery. However for some javascript libraries that aren't in node_modules that may exist in a more traditional setup like:
/src
/lib
/vendor
/fooLibrary
fooLibrary.js
fooLibrary.css
What I would like is to move these files into the vendor bundle but cannot work out how to specify these files in the vendor entry point.
You can set abs path to vendor lib
var webpack = require("webpack");
module.exports = {
entry: {
app: "./server.js",
vendor: ["/mylib/"],
},
output: {
filename: "bundle.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.bundle.js")
]
};
and webpack build lib from abs path to vendor bundle.
But import worked only if index.js exist, so before you should rename vendor file module to index.js with webpack copy plugin or use any tasks script for instance gulp task.