How to include Foundation 6 JS files via ES6 import? - javascript

I am using gulp with browserify + babelify to compile my JS.
My task looks like that:
import config from '../config.json';
import gulp from 'gulp';
import browserify from 'browserify';
import babelify from 'babelify'
import browserSync from 'browser-sync';
import babel from 'gulp-babel';
import source from 'vinyl-source-stream';
function onError(error) {
console.log(error.toString());
this.emit('end');
}
export function dev() {
return browserify({
entries: 'src/js/main.js',
debug: true,
extensions: ['.js', '.json', '.es6']
})
.transform(babelify)
.bundle()
.on('error', onError)
.pipe(source('main.js'))
.pipe(gulp.dest('public/js'))
.pipe(browserSync.stream());
}
gulp.task('js:dev', dev);
In src/js/main.js I am trying in import Foundation JS module. This file consists only one line:
import 'foundation-sites/js/foundation.util.motion';
After compilation I get non compiled foundation module with some browserify and babelify code:
BUT! I tried to copy file from node_modules to src folder and import it:
import './inc/app';
And in this case al works fine:
Why? What the magic? What will be the right way?

The problem is that you are trying to import a source file of foundation-sites package. You must use the bundled version or the single source file already transpiled present on node-modules/foundation-sites/dist/plugins/foundation.util.motion.
Then replace your import with this and it will work:
import 'foundation-sites/dist/plugins/foundation.util.motion';

Related

importing css/sass files in webpack using aliases

Is there any way to import .scss / .css files using aliases
// webpack.config.js
resolve: {
alias: {
styles: path.resolve(__dirname, "src/styles/"),
}
}
and in main.js
// main.js
import "styles/main.scss";
Webpack alias' should be prefoxed with tilde in sass imports. So your syntax should be:
import "~styles/main.scss";

Webpack is erroring when I attempt to import a directory containing modules

I'm trying to create a small npm library to make interfacing with an API a little neater. My folder structure is as follows...
dist/
index.js
src/
index.js
endpoints/
endpoint1.js
package.json
webpack.config.js
Within my src/index.js file I have..
import {endpoint1} from './endpoints'
module.exports = class lib {
...
}
When I npm run build (which runs webpack --display-error-details --mode production) webpack throws a big error saying "Module not found: Error: Can't resolve './endpoints' in 'my\project\dir\src'.
My webpack.config.js file currently looks like...
const path = require('path');
module.exports = {
mode: 'production',
entry: path.join(__dirname, '/src/index.js'),
output: {
path: path.resolve('dist'),
filename: 'index.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /.js?$/,
exclude: /(node_modules)/,
use: 'babel-loader'
}
]
},
resolve: {
modules: [
path.resolve(__dirname, 'src/endpoints')
],
extensions: ['.js']
}
};
I can see similar questions have been asked before and the resolutions listed don't seem to work for me so I thought I'd post it incase im making a rookie error. If any more info is required just say! Sorry if it's fairly wall of texty. Thanks.
The correct import would be:
import endpoint1 from 'endpoint1';
By using resolve.modules you tell Webpack to look up non relative paths in that folder. The module name is "enpoint1".
But actually you should only do this with libraries that you use across your project, for an endpoint a relative import will be appropriate:
import endpoint1 from "./endpoints/endpoint1";
import {endpoint1} from './endpoints' means this:
import from file ./endpoints/index.js something that is exported under the name enpoint1 in that file. If you import directory then it refers to index.js under that directory, not to all other files. It doesn't exist in your setup.
Names inside {} refer to named imports. This goes only for es6 modules-style imports like import {...} from. If you ommit {} then you import the default. CommonJs-style imports like const {...} = require('') work differently. CommonJs does not have named imports and exports. It just will import default from that file and then fetch a field via object destructuring.
What you export is something unnamed(i.e. default) from file ./endpoints/enpoint1.js
Something is unnamed because you use module.exports = which is CommonJS-style export. CommonJS does not support named exports. This is equevalent to export default class lib ... in es6 modules-style exports.
IF you want to import many files under directory you can consider these solutions:
1) Often single import points are created. You make a index.js file. In it you import manually every file under the directoy that you want to export. Then you export it under names. Like this:
import a from './a.js';
import b from './b.js';
import c from './c.js';
export { a, b, c };
Then it will work
2) In some rare cases in might make sence to use fs.readdir or fs.readdirSync to scan the entire directory and dynamicly require files in a loop. Use it only if you must. E.g. db migrations.

Webpack alias in Laravel Mix to node_modules

I would like to use an alias in VUE.JS in a Laravel 5.8 project to import css and js I have in my module.
webpack.mix.js
mix.webpackConfig({
resolve: {
alias: {
'alias': path.resolve(
__dirname,
'~myModule/src'
)
}
}
});
In my VUE App.js I would like import the css folder and I wrote:
resources/js/app.js
// css files
import 'alias/lib/css'
// js files
import 'alias/lib/script'
But I'm wrong something becouse the alias is not resolved:
ERROR in ./resources/js/app.js
Module not found: Error: Can't resolve 'alias/lib/css' in...
Can you help me to fix the issue?
After so many attempts I got the issue. The code was good but I was missing to load the webpack.mix.js properly:
From Laravel Mix documentation:
The webpack.mix.js file is your entry point for all asset compilation. Think of it as a light configuration wrapper around Webpack. Mix tasks can be chained together to define exactly how your assets should be compiled.
But if you are using npm run watch it is not (re)loaded before to compile new changed assets. This means:
if you are in watch mode (npm run watch) exit and restart it to load new updated webpack.config.js if you changed it.
Finally it worked! And it resolve new alias properly!
Here the final config I used in webpack.config.js:
mix.webpackConfig({
resolve: {
alias: {
'aliasName': path.resolve(
__dirname,
'node_modules/MyModule/src/'
)
}
}
});
Another alternative is:
mix.webpackConfig({
resolve: {
modules: [
'node_modules'
],
alias: {
'aliasName' : 'MyModule/src/'
}
}
});
Then in my Vue component (or in vue app.js, just in case)
<template>
<myModule-component></myModule-component>
</template>
require('aliasName/lib/css'); // to load full css directory
require('aliasName/lib/script'); // to load full js directory
import MyModuleComponent from 'aliasName/widgets/MyModuleComponent.vue'
...
export default {
...
components: {
'myModule-component': MyModuleComponent
}

Why is Browserify making my compiled Javascript file huge in file size?

I'm using Browserify with Gulp to compile some ES6 -> ES5 and doing basic concatenation for my files. Right now all my project has is different Javascript files that allow a user to upload files to a Google Cloud bucket.
When I test some things out by only compiling one of my files, Browserify, for some reason, compiles my Javascript into a huge file that is over 2MB. After further inspection, it seems that Browserify is taking its dependencies and adding it to my file which seems unnecessary.
The main problem is that Browserify is including its own node_modules in my outputted Javascript.
Below are some file setup examples with the output I'm receiving.
Test Javascript File (text.js)
This is a simple file that uses an npm package to send a text when something has been uploaded and exports the needed function.
'use strict'
function sendText(name) {
// Twilio Credentials
var accountSid = '<SID NUMBER>';
var authToken = '<AUTH NUMBER>';
//require the Twilio module and create a REST client
var client = require('twilio')(accountSid, authToken);
client.messages.create({
to: '<TO NUMBER>',
from: '<FROM NUMBER>',
body: 'Body text here',
}, function(err, message) {
console.log(message.sid);
});
}
module.exports = {
sendText: sendText
}
I'm referring text.js in an index.js file that will include all the scripts and serve as an entry file for Browserify.
index.js
import sendText from './uploads/text.js';
Browserify Task
import gulp from 'gulp';
import gulpif from 'gulp-if';
import gutil from 'gulp-util';
import source from 'vinyl-source-stream';
import streamify from 'gulp-streamify';
import sourcemaps from 'gulp-sourcemaps';
import rename from 'gulp-rename';
import watchify from 'watchify';
import browserify from 'browserify';
import babelify from 'babelify';
import uglify from 'gulp-uglify';
import browserSync from 'browser-sync';
import debowerify from 'debowerify';
import handleErrors from '../util/handle-errors';
import config from '../config';
function buildScript(file, watch) {
// Takes a our specified index.js file as the entry point for compiling
let bundler = browserify({
entries: ['./src/assets/js/' + file],
debug: false,
cache: {},
packageCache: {},
fullPaths: global.isProd ? false : true
});
// Watch for changes in javascript
if ( watch ) {
bundler = watchify(bundler);
bundler.on('update', rebundle);
}
// ES5 -> ES6
bundler.transform(babelify);
bundler.transform(debowerify);
// Rebundle any changes appllied
function rebundle() {
const stream = bundler.bundle();
gutil.log('Rebundle...');
// Check for errors in stream + listen for production environment
return stream.on('error', handleErrors)
.pipe(source(file))
.pipe(gulpif(global.isProd, streamify(uglify())))
.pipe(streamify(rename({
basename: 'main'
})))
.pipe(gulpif(!global.isProd, sourcemaps.write('./')))
.pipe(gulp.dest(config.dest.js))
.pipe(gulpif(browserSync.active, browserSync.reload({ stream: true, once: true })));
}
return rebundle();
}
gulp.task('browserify', function() {
// Only run watchify if NOT production
return buildScript('index.js', !global.isProd);
});
Pasting the output code was too large even for paste bin, so I'm not sure what information from that could be helpful, but I can provide anything that is needed.

How do I keep bower package dependencies out of my rollup bundle?

I'm currently creating a bower package that exports a single ES6 module.
When building the dist for my package, I'm using rollup to move all my internal modules into a single module, exporting only the one module.
Gulp task:
// Bundle ES6 modules into a single file
gulp.task('bundle', function(){
return gulp.src('./src/GuacaMarkdownEditor.js', {read: false})
.pipe(rollup({
// any option supported by rollup can be set here, including sourceMap
// https://github.com/rollup/rollup/wiki/JavaScript-API
format: 'es6',
sourceMap: true
}))
.pipe(sourcemaps.write(".")) // this only works if the sourceMap option is true
.pipe(gulp.dest('./dist'));
});
This all works fine, but I'm importing some dependencies from other bower packages which I don't want to bundle with my module (jQuery, font-awesome).
My problem is this: How can I keep bundling MY code and keep the ES6 import statements for bower packages - but without rollup bundling the external code into my bundle?
Example:
"use strict";
import $ from 'jquery'; // dont bundle this!
import GuacaAirPopUp from './GuacaAirPopUp'; // bundle this!
export
default class GuacaMarkdownEditor {
...
}
You can use this rollup plugin rollup-plugin-includepaths.
It allows you to import modules by name and define modules should be excluded from the bundle. I used it in a rollup.config.js:
import babel from 'rollup-plugin-babel';
import includePaths from 'rollup-plugin-includepaths';
var includePathOptions = {
paths: ['es6'],
include: {
'd3': './global/js/' + 'base/d3.min' // include library in es6 modules
},
external: ['d3'] // but don't bundle them into bundle.js
};
export default {
entry: './es6/entry.js',
plugins: [
includePaths(includePathOptions),
babel()
],
format: 'amd',
dest: 'build/bundle.js',
sourceMap: true
};
And in the es6 modules:
// not using relative path since it is handled by the plugin
import d3 from 'd3';
import other from 'otherModules';
//...
More discussion about external resolution here
It seems that rollup will detect named imports (as opposed to relative paths), as external dependencies.
When bundling this module:
import GuacaAirPopUp from './GuacaAirPopUp';
import ControlHandlerService from './ControlHandlerService';
import DefaultHandlerConfig from './DefaultHandlerConfig';
import toMarkdown from 'to-markdown';
import $ from 'jquery';
The bundler gave these messages:
Treating 'to-markdown' as external dependency
Treating 'jquery' as external dependency
When bundling the application that used this module, jquery was imported correctly using browserify.
Answered already by anthr however if you want to exclude your own made modules down below I believe is a clear explanation.
https://github.com/rollup/rollup/wiki/JavaScript-API#external
A list of IDs of modules that should remain external to the bundle
// main.js
import myMod from './my-module'; // <-- this module you don't wanna import
// build.js <--- gulp file
import * as path from 'path';
//...more of you gulp file code
rollup.rollup({
entry: 'app.js',
external: [
'./my-module', // <--- node module to be excluded from the bundle
path.resolve( './src/special-file.js' ) // <--- file you made to be excluded from the bundle
]
}).then(...)
//...more of you gulp file code
// Bundle ES6 modules into a single file
gulp.task('bundle', function(){
return gulp.src('./src/GuacaMarkdownEditor.js', {read: false})
.pipe(rollup({
// any option supported by rollup can be set here, including sourceMap
// https://github.com/rollup/rollup/wiki/JavaScript-API
format: 'es6',
sourceMap: true
}))
.pipe(sourcemaps.write(".")) // this only works if the sourceMap option is true
.pipe(gulp.dest('./dist'));
});

Categories

Resources