I have a Vue app created with vue create app and have the following settings in the babel.config file:
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
]
}
My Vue config file also looks like this:
module.exports = {
configureWebpack: {
optimization: {
splitChunks: false
}
},
css: {
extract: false,
}
}
At the moment when I run vue-cli-service build it compiles all my modules and styles into 1 bundled JS file.
There is an issue however with one of my NPM modules: socket.io-client
It appears that the way that Vue is compiling my app, it is not transpiling something within this package which is causing syntax errors in Internet Explorer 11.
I am fairly sure the problematic code in socket.io-client lies with one of it's dependencies called debug.
What I would like to do is have this package (socket.io-client) also transpiled so that I don't get the error in IE11.
I would have thought that Vue CLI would do this out of the box when you run the build but perhaps something has been setup wrong in my babel or Vue configuration? How could I resolve this issue?
Thanks!
You can use transpileDependencies option in your vue.config.js.
By default babel-loader ignores all files inside node_modules. If you want to explicitly transpile a dependency with Babel, you can list it in this option.
Example:
module.exports = {
...
transpileDependencies: [
'socket.io-client'
]
}
Found the issue here:
https://github.com/socketio/socket.io-client/issues/1328
Reverting the problematic package to previous version fixed it
Related
I have created a simple github repo to reproduce my scenario.
I have 2 config files: dev.vue.config.js and prod.vue.config.js that are used depending on NODE_ENV value
For prod my webpack entry point is set as
configureWebpack: {
entry: {
activitySubmit: './src/as-setup.js'
}
}
and I also use SplitChunks plugin to bundle node_modules into vendors.js so I expect webpack to produce 2 files: activitySubmit.js and vendors.js
However I'm also getting 3rd file app.js which has contents of src/main.js but why ? I'm not specifying it as my entry point and no other file is importing anything from main.js so why is it getting bundled anyway ? I don't need it in prod.
Now, if I change the entry point to
configureWebpack: {
entry: {
app: './src/as-setup.js'
}
}
I get 2 files: app.js and vendors.js
and if I inspect app.js I can see that it now does not contain code from src/main.js (as expected).
I'm confused, please help explain the logic
This question got answered on Vue Forum so I'm posting the answer here as well
Running
vue inspect --mode production
will show the Webpack configuration that Vue CLI is generating. It ends up with:
entry: {
app: [
'./src/main.js'
],
activitySubmit: './src/as-setup.js'
}
because as explained in vue docs, the configuration you provide in configureWebpack is merged using webpack-merge, so the default entry is still present.
I've created a brand new react app
create-react-app demo
I need to create alias for some directories/components like:
import { Header } from '#uicomponents'
Where #uicomponents is shortcut for the path 'src/hello/this/is/the/path/to/ui/components '
All online tutorials telling that I can use alias imports using resolve.alias, but I'm wondering how to do this with brand-new react app?
Theres is no .babelrc or webpack.config.js files.
Any help please?
If you haven't ejected your application from CRA, then you can alias your source directory with using NODE_PATH in your .env file. NODE_PATH=/src/hello/this/is/the/path/to/ui/components.
If you alias without ejecting, it won't allow you to do the #uicomponents or have multiple aliases. Here's an issue on GitHub that talks about it and the relevant CRA page on environment variables.
If you have ejected you can set the alias in the Webpack configuration files and be able to import like you want:
...
resolve: {
alias: {
'#uicomponents': '/src/hello/this/is/the/path/to/ui/components'
}
},
...
UPDATED:
I recommend you to use Craco.
It allows you to customize webpack / babel / any other tool that used in react-scripts internally.
Webpack and Jest aliases is not an exception.
And recently I created a plugin called craco-alias specially for these purposes.
Links: GitHub, npm.
This plugin generates webpack and jest aliases for you automatically.
You just need to install Craco, write a small config for it, then create (or edit) your jsconfig.json / tsconfig.json (it works with TS as well) and specify aliases source in craco-alias config object.
It's easy - you can find all examples on README page.
Of course it works with every command (npm start, npm test, run build build) and allows to pass any CLI arguments.
But, the only problem is that plugin only supports path aliasing, and it doesn't work with module aliases properly.
I hope it will help somebody :)
The alias solution for craco or rewired create-react-app is react-app-alias for systems as: craco, react-app-rewired, customize-cra
According docs of mentioned systems replace react-scripts with craco in package.json and configure next:
// craco.config.js
const {CracoAliasPlugin} = require('react-app-alias')
module.exports = {
plugins: [
{
plugin: CracoAliasPlugin,
options: {}
}
]
}
Configure aliases in json like this:
// tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"example/*": ["example/src/*"],
"#library/*": ["library/src/*"]
}
}
}
And add this file in extends section of main typescript config file:
// tsconfig.json
{
"extends": "./tsconfig.paths.json",
// ...
}
I have a hypothetical Typescript file in my project (simplified example).
Utils.ts:
import * as HelperFromNodeModules from 'helper-from-node-modules';
class Utils {
static foo() {
return HelperFromNodeModules.parse(...);
}
}
Importing helper-from-node-modules consists of a Javascript file.
helper-from-node-modules.js:
const dep = require('foo');
function parse(...) {
return bar.map((e) => {...});
}
And from #types/helper-from-node-modules index.d.ts:
export function parse(...);
The tsconfig.json among other things contains the following:
{
...
"target": "es5",
"lib": ["es2015.collection","es6", "dom"],
"sourceMap": true,
"allowJs": true,
...
}
So my problem is the Typescript compiler's output file is a giant concatenation of my compiled source code plus all of the decencies. Since helper-from-node-modules was always a .js file, the compiler seems to just append its contents to the output file. So, despite "target": "es5" the output file still contains es6 artifacts like const and (e) => {...}, resulting in errors with things later that expect strictly es5 javascript.
Is there is a way to tell the Typescript compiler/transpiler to output es5 on the javascript dependencies as well?
Context if you care:
I made the horrible mistake of using react-create-app-typescript and react-scripts-ts as the boilerplate for my React app. The webpack stack built in is very opinionated on where source code should come from and that the compiled source must be es5. The minifier/uglifier packaged will crash if attempting to minify any es6 artifacts. I know I can run npm run-script eject and modify the various config scripts but I am trying to avoid that mess. I would love to just get the source to compile to es6 and not mess with their webpack stack.
Unfortunately, there isn't a way to do convert dependencies from ES6 to ES5. That option in tsconfig.json only affects how TypeScript code is transpiled. What you should do is use an ES5 version of your helper-from-node-modules. For example, Angular is distributed with several packages, for ES5 (umd), ES5, ES6 ... Then, in the package.json of the library there are options to tell the packager (usually webpack) what version to use, depending on the target use for TypeScript.
If the library you're using does not support that, the only option you have is to transpile it to ES5 yourself, maybe using babel, or use an alternative.
Is is strange, however, for a library to be only distributed as ES6.
The only thing that comes to my mind is hooking into the compilation process and transforming your dependencies before they get processed by TypeScript. This requires TypeScript transformers.
A transformer is a function to which the AST of your program is exposed. A basic example:
import * as ts from 'typescript';
export default (program: ts.Program) => {
return (ctx: ts.TransformationContext) => {
return (sourceFile: ts.SourceFile) => {
function visitor(node: ts.Node): ts.Node {
/**
* If that's the kind of node you were looking for,
* do something with it and return it. Otherwise:
*/
return ts.visitEachChild(node, visitor, ctx);
}
return ts.visitEachChild(sourceFile, visitor, ctx);
};
};
}
If you are using Webpack, you could plug it into your build pipeline in your Webpack configuration file.
webpack.config.js
const transformer = require('./your-custom-transformer');
module.exports = {
/* ... */
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader', // (or 'awesome-typescript-loader')
options: {
getCustomTransformers: program => ({
before: [
transformer(program)
]
})
}
}
]
}
};
Came across this question because I needed to import some files into both Next.js and my CLI. (A common source file in two different builds.) Next.js has certain automated configuration, so I was trying to support all the things it supports so I didn't have many situations where Next.js worked and my CLI failed.
So the below solution is the Babel part. (I combined with https://github.com/vercel/next.js/tree/canary/examples/custom-server-typescript for the tsconfig part.)
Solution to transpile ES6 imports to ES5: (outside of nextjs)
from https://www.dotnetcurry.com/javascript/1293/transpile-es6-modules-es5-using-babel
npm install --save-dev #babel/cli #babel/preset-env
Create .babelrc:
{
presets: ["#babel/preset-env"]
}
add to your build script (i.e. you probably already have package.json script for npm run build to work)
for JSX to work (if you have any .tsx files or JSX syntax in .js files)
npm install --save-dev #babel/preset-react
and in .babelrc
{
"presets": [
"#babel/preset-env",
[
"#babel/preset-react",
{
"runtime": "automatic"
}
]
]
}
for Next.js _app had to add https://github.com/uiwjs/babel-plugin-transform-remove-imports to remove CSS imports
I am trying to use this with my webpack project
https://blog.meteor.com/leverage-the-power-of-meteor-with-any-client-side-framework-bfb909141008
but I get this error
ReferenceError: __meteor_runtime_config__ is not defined
Here are the steps I did
create a new meteor project
then I run the client bundler like this
meteor-client bundle —source=./ —destination=./meteor-client.bundle.js —config=meteor-client.config.json
and here is the config
{
"runtime": {
"DDP_DEFAULT_CONNECTION_URL": "http://localhost:3000"
},
"import": [
"meteor-base#1.3.0",
"mongo#1.4.2",
"reactive-var#1.0.11",
"jquery#1.11.10",
"tracker#1.1.3",
"shell-server#0.3.1",
"react-meteor-data"
]
}
then I copy my meteor-client.js to my webpack project node_modules
and import it like this
import 'meteor-client'
then I bundle webpack and run dev-server and I get the above mentioned error.
I had the same issue, and fixed that by putting my meteor-client.js to node_modules and exclude node_modules from processing by babel-loader with webpack (or you could just exclude meteor-client.js). Raw loading will workaround that.
In case someone still searching.
I have two modules inside the same directory, managed both by lerna js. One of them is a library that others module includes. Both of them packed by webpack following webpack library authoring.
But, when I launch webpack in the app dir, the process includes all library/node_modules dependencies inside the app, for example vue.js. In library vue is "devDependency" while in the app is "dependencies". This implies two Vue context in navigator. Somebody known why?
Thanks.
You need to add an alias:
module.exports = {
...
....
},
resolve: {
modules: ["node_modules",
alias: {
'vue$': 'vue/dist/vue',
'jquery': 'jquery/dist/jquery.min.js'
}
},
...
Thanks to #evocateur
"Node resolves symlinks when requiring, which means libraries (like React and Vue) that are singletons will break. You need to add resolve.alias webpack config so it always chooses the "root" node_modules packages."
Putting in webpack following works perfectly in resolve.alias:
vue: path.resolve(__dirname, './node_modules/vue/')