Webpack bundle named requirejs modules - javascript

In my company we have a significant AMD RequireJS code base and I am trying to use webpack to bundle some of it.
Here is what the architecture looks like:
somedir
│ app.js
│
└───anotherdir
|
├─── module1
│ file1.js
│ file2.js
│
├─── module2
│ file3.js
│
└─── module3
file4.js
file5.js
file6.js
Each file is written like that :
define('ATAG/MODULE/ID, ['somedeps'], function (somedeps) {});
So for instance file1.js could look like
define('ATAG/module1/file1, [], function () {});
And we have a RequireJS config which maps ATAG to anotherdir and we possibly have some more config for different tags.
Now I am trying to create a bundle from app.js with webpack but I have no idea of how to replicate the behavior we have with require.config({ paths: { ATAG: 'anotherdir' } }).
So far my attempts with resolve.alias have not been successful.
Is it even possible to achieve something like this with webpack based on our usage of RequireJS (not requiring relative paths) ?
Thank you.

You were on the right path with resolve.alias:
// foo.js
var a = require('ATAG'); // resolved to anotherdir/index.js
var b = require('ATAG/bar'); // resolved to anotherdir/bar.js
// webpack.config.js
const path = require('path');
module.exports = {
entry: './foo',
output: {
filename: 'bundle.js'
},
resolve: {
alias: {
ATAG: path.join(__dirname, '/anotherdir')
}
}
};

Related

Using TailwindCSS with Symfony Webpack Encore

I'm having trouble setting up TailwindCSS with Symfony and I'm not sure what's wrong
webpack.config.js
var Encore = require('#symfony/webpack-encore');
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
.setOutputPath('public/build/')
.setPublicPath('/build')
.addStyleEntry('tailwind', './assets/css/tailwind.css')
.enablePostCssLoader((options) => {
options.config = {
// directory where the postcss.config.js file is stored
path: './postcss.config.js'
};
})
.splitEntryChunks()
.enableSingleRuntimeChunk()
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
.enableVersioning(Encore.isProduction())
.configureBabelPresetEnv((config) => {
config.useBuiltIns = 'usage';
config.corejs = 3;
})
;
module.exports = Encore.getWebpackConfig();
tailwind.css
#tailwind base;
#tailwind components;
#tailwind utilities;
postcss.config.js
let tailwindcss = require('tailwindcss');
module.exports = {
plugins: [
tailwindcss('./tailwind.config.js'), // your tailwind.js configuration file path
require('autoprefixer'),
require('postcss-import')
]
}
tailwind.config.js
module.exports = {
theme: {
extend: {}
},
variants: {},
plugins: [],
prefix:,
}
Here is the output of yarn encore dev
yarn run v1.22.0 Running webpack ...
ERROR Failed to compile with 1 errors
error in ./assets/css/tailwind.css
ValidationError: Invalid options object. PostCSS Loader has been
initialized using an options object that does not match the API
schema.
options has an unknown property 'config'. These properties are valid: object { postcssOptions?, execute?, sourceMap? }
Entrypoint tailwind = runtime.js
ModuleBuildError: Module build failed (from
./node_modules/postcss-loader/dist/cjs.js): ValidationError: Invalid
options object. PostCSS Loader has been initialized using an options
object that does not match the API schema.
options has an unknown property 'config'. These properties are valid: object { postcssOptions?, execute?, sourceMap? }
at validate (./node_modules/schema-utils/dist/validate.js:104:11)
at Object.loader (./node_modules/postcss-loader/dist/index.js:43:29)" -t "Webpack
Encore" error Command failed with exit code 2. info Visit
https://yarnpkg.com/en/docs/cli/run for documentation about this
command
I have node v14.15.0, I tried to yarn upgrade. Here are my direct dependencies :
success Saved lockfile.
success Saved 598 new dependencies.
info Direct dependencies
├─ #symfony/webpack-encore#0.33.0
├─ autoprefixer#10.1.0
├─ core-js#3.8.1
├─ datatables.net#1.10.22
├─ postcss-import#13.0.0
├─ postcss-loader#4.1.0
├─ postcss#8.2.1
├─ regenerator-runtime#0.13.7
├─ tailwindcss#2.0.2
└─ webpack-notifier#1.12.0
Like I said previously, I'm not sure what is wrong and my attempt to correct the problem on my own failed. The error seems to be coming from postcss or at least something inside my file that postcss doesn't like.
Could someone explain me where is this error coming from and how to correct it ?
Looks like postcss-loader has changed their api already by moving config option into postcssOptions instead.
Let's try with new option as following:
Encore
// ...
.enablePostCssLoader((options) => {
// new option outlined here https://webpack.js.org/loaders/postcss-loader/
options.postcssOptions = {
config: './postcss.config.js',
},
})

Using require as if is running 'cd ./folder && node file.js'

I have the following structure
├── testFolder
└──subTestFolder
test.ts
index.ts
└── foo
└── beta.ts
├──text.json
Based in this, I'm trying to require the test.js inside beta.js based in test.js absolute path.
But when I ran ts-node ./foo/beta.js, it throws Cannot find module '../text.json
test.js Content:
require("../index.js");
beta.js content:
const file = 'D:\testFolder\subTestFolder\test.js';
const dir = path.dirname(file);
process.chdir(dir);
require(file);
index.ts
const json= fs.readFileSync('../corde.json').toString();

gulp-eslint not linting .js files inside of a dot directory

I have .js files inside of a dot directory that are not being linted by gulp-eslint.
Example: .foo/file1.js
I've confirmed that the glob is picking up the files inside of the dot directory.
gulp-eslint is passing successfully for the files inside of a parent dot directory even when an intentional error is introduced inside these files.
I've confirmed that directories without a . in the name of the directory (e.g. src/file.js, etc.) are failing linting, when the same intentional error is introduced.
My project structure is something like this:
project/
│
├── .foo/
│ ├──file1.js
│ └──file2.js
│
├── src/
│ ├──file1.js
│ └──file2.js
│
├── gulpfile.js
└── .eslintrc
Contents of gulpfile.js
const gulp = require('gulp');
const eslint = require('gulp-eslint');
gulp.task('lint', () => {
return gulp.src([ './src/**/*.js', './.foo/**/*.js' ])
.pipe(eslint({
configFile: './.eslintrc'
}))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
Contents of .eslintrc
// Reducing down to a single, simple rule
{
"env": {
"es6": true
},
"rules": {
"quotes": [
"error",
"single"
]
}
}
Is there something incorrect in my config that is preventing the .js files inside of the dot directory .foo from being linted?
Thanks!
It looks to be a known "quirk" of eslint (as of 6.8.0).
The workaround (until a PR is merged to fix this) is to use an .eslintignore file to unignore dot directories explicitly:
#.eslintignore
!.foo

Cannot find module with Webpack, Typescript, custom module directory

What I'm trying to do
I am wrote a dummy module my-component which essentially exports a single class Something. I placed it in app/modules/. Now I am tying to access it using the import Syntax from app/app.js:
import { Something } from 'my-component';
Expectation: With my current Webpack configuration (below) I would expect this to work.
Actual: This throws the error:
ERROR in [default] /<project_dir>/app/app.ts:1:26
Cannot find module 'my-component/Something'.
What I tried to fix it
I know the module in itself is defined correctly, because
I can import it using a relative path: import { Something } from './my-component'
I can import it as-is, if I move the module to node_modules/my-component.
The only combination that fails is importing it without a relative path from my modules/ directory. So I think the issue might be my Webpack configuration.
Setup Details
As you can see below, I have two directories listed as resolve.root:
project_dir/app
project_dir/node_modules
It seems to manage to resolve from node_modules, just not from app.
Project layout
Webpack
project_dir/
├── app/ context, resolve.root
│ ├── app.ts
│ └── my-component/
│ ├── index.ts
│ └── Something.ts
├── webpack.config.js
├── node_modules/ resolve.root
│ ├── ...
│ ├── ...
│ └── ...
└── dist/
└── ...
app/app.ts
import { Something } from 'my-component/Something';
app/my-component/index.ts
export { Something } from './Something'
app/my-component/Something.ts
class Something {
}
export { Something };
webpack.config.js
var path = require('path'),
ROOT = path.resolve(__dirname, '.');
module.exports = {
context: path.resolve(ROOT, 'app'),
entry: 'app.ts',
output: {
path: path.resolve(ROOT, 'dist'),
filename: '[name]-[hash].js'
},
module: {
loaders: [
{ test: /\.ts$/, loader: 'awesome-typescript' }
]
},
resolve: {
root: [
path.resolve(__dirname, 'app'),
path.resolve(__dirname, 'node_modules')
],
extensions: [
'', '.ts', '.js'
]
}
};
EDIT
Fixed the project layout.
Cannot find module
If you experience this issue with dynamic module loading using ESNEXT,
you have to add "moduleResolution": "node" to your tsconfig.json.
I found an easier solution than the previously accepted one:
In your typescript configuration, set the baseUrl in the compilerOptions:
tsconfig.json:
{
"compilerOptions": {
"baseUrl": "./app",
...
},
...
}
Explanation:
Webpack and Typescript use node module resolution by default, which is fine.
When setting up custom module folders though, you need to configure them in both the Webpack and the Typescript config.
Changes to the Webpack module resolution config are not propagated to the Typescript compiler.
Ok. I created a replica of your project structure. It seems that the case is that the import statement does not behave the same as the require, AND, webpack resolve.root config works as expected with it.
For the modules, change your import statements to require like this:
app.ts
// Define require function for TypeScript to know that it
// will exist at runtime
declare function require(name:string);
// Require your module
var Something = require('my-component/Something');
// var myComponent = require('my-component');
my-component/Something.ts
// Export something (used a function to test)
export function Something() {
console.log("Hello");
}
my-component/index.ts
// Definition of require function as mentioned before
declare function require(name:string);
// Passing other modules
var exportedModules = {
Something: require("my-component/Something")
};
export default exportedModules;
Like this, it will work without problems and resolve with the module names as you defined in Webpack. Unfortunately, I couldn't achieve it with the import.
I pushed the solution to a repository. Check it out if you need!

Gulp.js: how to rewrite relative paths?

Structure:
static
├── build
│ ├── css
│ ├── fonts
│ ├── img
│ └── js
└── src
├── blocks
├── fonts
└── img
Piece of gulpfile.js:
var path = {
build: {
js: 'static/build/js',
css: 'static/build/css',
fonts: 'static/build/fonts',
img: 'static/build/img'
},
src: {
vendor_fonts: ['bower_components/**/*.{svg,woff,eot,ttf}', 'semantic/**/*.{svg,woff,eot,ttf}'],
vendor_img: ['bower_components/**/*.{png,jpg,jpeg,gif}', 'semantic/**/*.{png,jpg,jpeg,gif}']
}
};
gulp.task('vendor:img', function(){
return gulp.src(path.src.vendor_img)
.pipe(imagemin({
progressive: true,
interlaced: true,
use: [pngguant()]
}))
.pipe(gulp.dest(path.build.img))
});
gulp.task('vendor:fonts', function() {
gulp.src(path.src.vendor_fonts)
.pipe(gulp.dest(path.build.fonts))
});
When i build 3-party packages (such as fotorama or semantic ui), they have a relative paths - as a result, main.css have only relative paths and server cant't find them.
How i can solve this?
If your gulpfile.jss is in your root you should be able to just prefix your paths with nodes Global Object __dirname
__dirname#
{String}
The name of the directory that the currently executing script resides in.
Example: running node example.js from /Users/mjr
console.log(__dirname);
// /Users/mjr
__dirname isn't actually a global but rather local to each module.
https://nodejs.org/api/globals.html#globals_dirname
So if your gulpfile was in your root in your paths just do
__dirname + "/build/whatever/whatever";
This all being if I understand your question correctly.

Categories