Webpack Loader not Working on Jenkins CI Build - javascript

I'm trying to integrate Weback into my current project and am having problems with a custom loader I built to create a concat banner and footer around each module's file contents, and to inject the __filenamevalue. Everything works great doing local builds with grunt
https://github.com/optimizely/marketing-website/tree/dfoxpowell/jordan-webpack-try/grunt/webpack
grunt server
//or
grunt build --env=production //production build for uglify/dedupe
Our staging build on Jenkins successfully runs the loader using grunt staging-deploy --branch=$branch --env=production
Our production build uses a Docker container and a deploy.sh script which runs grunt build --env=production. This build for some reason fails to run the loader although grunt build --env=production locally will successfully run the loader and build the assets.
I resorted to hardcoding the loader into the repo and requiring it by path in the make-webpack.config.js in order to debug if this was some sort of installation issue on Jenkins but this didn't help.
https://github.com/optimizely/marketing-website/blob/dfoxpowell/jordan-webpack-try/loaders/inject-filename-loader.js
I know this is most likely a difficult question to answer without access to our Jenkins deploy environment but any info you could offer for help debugging would be extremely helpful.
I created an issue in the Weback repo here that basically states the same info as above.
Update
I took this suggestion Injecting variables into webpack and added
resolveLoader: {
modulesDirectories: ['loaders', 'node_modules'],
extensions: ['', '.loader.js', '.js']
}
to my webpack.config and put my loaders directory in the root of my project. Unfortunately, the result is still the same and the loader doesn't run in prod on Jenkins.

Here is the solution I found to this issue:
Our CI build was installing our project from Git as a node_module through NPM rather than using git clone. Therefore, there was a node_modules directory at the root of the CI build, and the project was being built inside of this directory.
node_modules/<project npm package name>/{node_modules,grunt/webpack/...configs}
Therefore, it seems the loader was being looked for in the wrong node_modules directory, but it is strange that other loaders that I was using such as babel and handlebars were being sourced correctly.
When I used the loader path directly in the loader config
var injectFilenamePath = path.join(process.cwd(), 'grunt/webpack/inject-filename-loader');
console.log('LOADER PATH => ', injectFilenamePath);
var loaders = [
{
test: /\.js$/,
exclude: [
/node_modules/,
/bower_components/,
/libraries/
],
loader: injectFilenamePath + '?' + opts.injectFileNameParams
},
{ test: /\.hbs$/, loader: 'handlebars-loader' },
{test: /\.js?$/, exclude: ['bower_components', 'node_modules'], loader: 'babel-loader'}
];
the console output was
LOADER PATH => /opt/tmp/node_modules/marketing-website/grunt/webpack/inject-filename-loader
and after cloning our repo rather than npm i the path was
LOADER PATH => /opt/tmp/marketing-website/grunt/webpack/inject-filename-loader
Not sure if this somehow expected behavior but hopefully it saves others from similar issues if they arise.

Related

How to make webpack-dev-server serve my index.html

I'm trying to get an extremely simple bare-bones TypeScript project setup with Webpack and I'm having an incredibly hard time for some reason.
I followed this guide and everything is working. When I simply run webpack my files will bundle and compile and be outputted into the dist directory. From there I can host them on a local server and it all works fine.
However, I want to avoid having to manually bundle and compile my code every single time I make a change, and I'd like for this to be done automatically each time I save my files. As far as I can tell this is a common use for Webpack and so I'm not sure why I'm having such an incredibly hard time finding any good information on it.
I decided to use the webpack dev server to accomplish this, so I read this tutorial and for the life of me I can't find anybody who explains how to get it to also server my index.html? When I run webpack serve --mode=development all goes well, and when I navigate to the localhost port that I server to I get a 404 error.
One of the "tips" on the previously linked page reads
If you're having trouble, navigating to the /webpack-dev-server route will show where files are served. For example, http://localhost:9000/webpack-dev-server.
When I navigate to localhost:1234/webpack-dev-server it tells me that it's only serving a single file: bundle.js Clearly a JavaScript file alone is not going to work, and I need it to also serve the index.html file that's in my dist directory.
Now, my knowledge here is very limited as this is my first time working with Webpack, but here's all the detail I can give and hopefully it's not accidentally totally unrelated:
Whenever my dev server reloads itself (whenever it's booted up or if a watched file changes while it's running) it only updates the bundle.js file that it's serving. It doesn't update the bundle.js file stored in my dist directory on my hard drive. How can I make it update both?
And also, how do I make the server also serve my index.html file instead of only the bundle.js? Where is it even getting that bundle.js from? Is it compiling all of my code from scratch to create that js file or is it taking that out of the dist directory?
And additionally, am I going about this totally in the wrong way? Where should my index.html even go? I put my TypeScript files into a src directory and they're converted to .js files and moved into my dist directory... Should I also put my index.html inside src or does it belong in dist or somewhere else entirely? When I put index.html in src it doesn't get copied over into dist, it just ignores it completely. If my index.html file doesn't belong in src it must belong in dist, but if it belongs in dist then how can I expect the dev server to find it and serve it along with the other TypeScript files in src? Why can't the dev server just serve everything in dist and automatically compile everything from src into dist? I must be misunderstanding the flow of it all, but I have no idea where to look for an explanation and I've been at this for several hours now.
Just a general explanation of how it all works would be very helpful as well, as I can't find a single article or forum post anywhere that details all the spaghetti going on with Webpack. I've been avoiding bundlers and all this NPM mess for as long as I can because I constantly run into issues like this, but I finally decided to jump in and just push through all the mess and I'm already regretting it. If someone could just point me (and other people having similar problems) to some good resources for learning about all the automagic going on that would be hugely appreciated. The Webpack documentation and guides are very much worthless to a newbie.
My Webpack config file:
const path = require("path");
module.exports = {
entry: "./src/index.ts",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
}
]
},
resolve: {
extensions: [".tsx", ".ts", ".js"]
},
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
devServer: {
compress: false,
static: false,
client: {
logging: "warn",
overlay: {
errors: true,
warnings: false
},
progress: true
},
port: 1234, host: "0.0.0.0"
}
};
Is your entry set in webpack? So that it is included?
entry: {
main: 'path/to/index.ts'
},
You could also try adding to your index.ts file
require('file-loader?name=[name].[ext]!../index.html');
Or
require("./src/index.html");
// Then In your webpack config file add a loader
loaders : { { test: /\.html/, loader: 'file?name=[name].[ext]' } }
Otherwise you could always copy this file over with webpack copy plugin
{
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
}
will need to run npm install --save-dev html-webpack-plugin to install it. As well as move your index.html file into your src folder
Please visit localhost:1234/bundle (Where bundle.js is your bundled file) the magichHTML route, which will load the HTML file with the bundled script.

How to install a npm package from local folder and develop on both the folder simultaneously?

I am working on a React project and using Webpack to compile the code. This project contains a lot of common components which is installed in other projects across the organisation using npm install private git repository.
Package.json of other project looks like this:
"#mypackage/my-package-name": "git+ssh://git#github.com:git-handle/git-repo.git",
And in Webpack config I am compiling it by excluding it from node modules and it works fine.
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules(?!\/#mypackage))/,
use: [
{
loader: 'babel-loader',
query: {
presets: ['#babel/react'],
},
},
],
},
],
},
Now when I want to update the code of common component from the global package I have to reinstall the whole package to check the changes.
One workaround for that is to edit the node_modules but then I have to redo those changes to my global package and again do the reinstalling process at the end ( also it doesn't keep the git history to track what changes needs to be done ).
I have came across npm install from local and npm link local folder answer but facing the same issue which is not resolved
Updated package.json
"#mypackage/my-package-name": "file:../my-package-name"
I got the following errors
Module not found: Can't resolve '#mypackage/my-package-name/Navbar' in 'path/to/folder/'
SassError: File to import not found or unreadable: bootstrap/variables
Module not found: Error: Can't resolve 'js-cookie'
These errors are may due to an incomplete compilation of code from local folder.
My folder structure is something like this
= (my-package)
- package.json
- ...
= src
- index.js
= (other-project)
- package.json
- ...
= src
- index.js
I am looking for a solution by which I can point the package to a local folder( mypackage global folder ) and synchronize the changes in both the projects.

Babel plugin transform-remove-console not working with Vue CLI 4 #vue/cli-plugin-babel/preset?

With a VueJS project created by Vue CLI 4, you get Babel configured with this handy preset in babel.config.js:
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset',
],
};
I'm trying to use babel-plugin-transform-remove-console to remove console.* from the built JS files.
Installed the plugin as a dev dependency by: npm i -D babel-plugin-transform-remove-console
Then modified babel.config.js:
module.exports = (api) => {
var env = api.cache(() => process.env.NODE_ENV);
var plugins = [];
// Change to 'production' when configs are working
if (env === 'development') {
plugins.push(['transform-remove-console', { exclude: ['error', 'warn'] }]);
}
return {
presets: ['#vue/cli-plugin-babel/preset'],
// plugins,
// Doesn't work even when always on?
plugins: ['transform-remove-console'],
};
};
This should work by running npm run serve -- --reset-cache, and I've also tried building the app many times with different environments, but the console loggings are still showing up in the browser's console?
Is Vue CLI's preset somehow mixing it up for not being able to set plugins via this configuration file?
UPDATE: Created a bug report to Vue CLI repo, and while creating a minimal bug reproduction repository, I found out this plugin is working with a new project.
However, I have no idea what is causing this as I've synced this application with the newest CLI bootstrapped template, and also tried nuking NPM cache by `npm cache clean --force.
I ran into the same problem. This did not work:
plugins: ['transform-remove-console']
But this worked:
plugins: [['transform-remove-console', { exclude: ['error', 'warn'] }]]
Hope this helps others who encounter the same issue.
It seems #Zydnar's suggestion of nuking node_modules folder may have helped, however, I also found out that my recent NPM packages upgrades had been interrupted and had not been fully successful. There was some Vue CLI plugins that had different versions.
After nuking node_modules and upgrading all the packages this Babel plugin started working!

Webpack - Bundle multiple/different versions of .css files

I would like to make my bundled .css file being generated by Webpack more configurable, so I can output different 'versions' - based on the same .css file - to make the life of developers working on my project in the future easier.
I would like to have the following steps:
Concat of all SCSS into CSS (bundle.css)
Minimize output of step 1 (bundle.min.css)
Embed all images from step 2 (bundle.b64.min.css)
Embed all fonts from step 3 (bundle.bs64.fonts.min.css)
In the end - after my build process -, I would have 4 distinct files in my dist folder. Would that me possible?
The way I'm currently doing it, I run a different script for each step - deletes dist folder, goes through project, produces the output. I would like to have a single script that does all of it at once without having to go through my project 4 times.
I kind of found a solution for it here:
Webpack Extract-Text-Plugin Output Multiple CSS Files (Both Minified and Not Minified)
But, for my specific case, I would have to return 4 different configurations in a array instead of a single object.
Ok so based on our comment conversation i'm gonna give you a workflow of steps 1-4, but with regular assets handling, not a bundling of assets (which i haven't heard of but maybe someone else can elaborate there).
So the steps:
bundle all scss files into 1 bundle.css
make sure this bundle is minified
add assets management to build for images
add assets management to build for fonts
The important things:
This workflow is basically a built by configuration. configuring the npm scripts with the package.json file, and configuring webpack with config.webpack.js. This will allow you to simply run 1 command to build your project: npm run build. note: For simplicity's sake i am going to ignore production/development/etc environments and focus on a single environment.
package.json:
This is used to set up the command that will actually run when you input npm run build in the terminal (from the project dir of course).
since we are avoiding different environments for now and as you are not using Typescript this is a very simple configuraton:
"scripts": {
"build": "webpack",
},
that's all you have to add. It sound's stupid now but when the project will get more complex you are going to like those scripts so better start off making them already.
webpack.config.js:
The major lifting will be made in this configuration file. This basically tells webpack what to do when you run it (which is what npm run build is doing).
first off let's install some plugins:
npm install --save-dev file-loader
npm install --save-dev html-webpack-plugin
npm install --save-dev mini-css-extract-plugin
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'production',
devtool: 'source-map'
entry: './client/src/app.jsx',
output: {
path: path.join(__dirname, 'client/dist/public'),
filename: 'bundle.[hash].js'
},
module: {
rules: [
{
test: /\.s?css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: false
}
},
'css-loader',
'sass-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}
]
},
resolve: {
extensions: ['.js', '.json', '.jsx']
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './client/src/index_template.html'
}),
new MiniCssExtractPlugin({
filename: 'style.[hash].css',
chunkFilename: '[id].[hash].css'
}),
]
};
Notice i've added the htmlWebpackPlugin because it makes it easier to reference the correct hashed bundles automatically. Also I've assumed the app is a react app but you can just change the entry point to where your app loads from.
This is quite hard to do of the fly without testing things out, but i hope this gives you enough reference as to what you should change and do to get going with it.
Again i strognly recommend the webpack.js guides and documentation, they are very thorough and once you start getting the hang of it things start working smoothly.

Why is Webpack looking for a preset in my home directory?

In the Webpack for a project I'm working on, I have Webpack set to do Babel transpiling so I can use Flow-typed JavaScript. However, when I run Webpack, which has this rule,
{
test: /\.js/,
exclude: ['/node_modules/'],
use: [{
loader: 'babel-loader',
options: {
presets: ['env'],
plugins: ['transform-flow-strip-types']
}
}]
}
I'm getting:
Module build failed: Error: Couldn't find preset "transform-flow-strip-types"
relative to directory "/home/andy"
Last time I was working on this, Webpack worked correctly and was searching for transform-flow-strip-types in my node_modules folder, but now it's looking in my home directory. Why would Webpack all of a sudden by looking in my home directory, or how would I be able to diagnose why that is?
This is an unfortunate footgun in Babel's config file parsing. It has traversed all the way out of your project and found an unrelated .babelrc file that is in your home directory.
There's pretty much never a reason to have a .babelrc there, so your best bet would be to delete /home/andy/.babelrc. Alternatively if that's actually something your wanted (if so, please reconsider :P), you could create a no-op .babelrc in your project with just an empty object in it, which would also fix the issue.
I'm currently working to make Babel stop searching for .babelrc files as soon as it finds any package.json but that has yet to land and would only apply to Babel 7.x, not the current 6.x release. https://github.com/babel/babel/pull/7358

Categories