Adding additional module export from external file to webpack bundle - json

I have a project that requires an additional "config" file that I would like compiled into the final webpack bundle as an additional export of the bundled library.
The condition is that this config file, shouldn't need to be added to the entry file, but simply added an an additional export to the bundle.
I'm still relatively new to Webpack, but have been looking into how I might be able to accomplish this for a while now with no avail. Any help on getting into the right direction would be greatly appreciated!
Entry File (ts, using ts-loader):
export default class TestPlugin {
this.name: string;
constructor(name: string) {
this.name = name;
}
}
Plugin "config".
{
"name": "test plugin"
}
Plugin "loader" logic (separate project).
const plugin = require(path.resolve(pluginDirectory, fileName)
const config = plugin.config
const newPlugin = new plugin(config.name)
Webpack Config.
entry: ['./src/index.ts'],
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
output: {
filename: 'example.plugin.js',
path: path.resolve(__dirname, 'build'),
library: 'plugin',
libraryTarget: 'umd',
libraryExport: 'default',
globalObject: 'this',
},

Related

the dist folder is not being created

i'm trying to build gulp on ES6 modules, I got stuck at the very first stage: the function of copying files from the src folder to dist does not work and does not create the dist folder itself, despite the fact that the terminal outputs work without errors. after I prescribed the watcher function and the same behavior, the file is created and tracking and copying is not performed, please help, I will be very grateful)
-gulpfile.js
import gulp from "gulp";
import { path } from "./gulp/config/path.js";
global.app = {
path: path,
gulp: gulp
}
import { copy } from "./gulp/tasks/copy.js";
function watcher() {
gulp.watch(path.watch.files, copy)
}
const dev = gulp.series(copy, watcher);
gulp.task('default', dev);
-path.js
import * as nodePath from 'path';
const rootFolder = nodePath.basename(nodePath.resolve());
const buildFolder = './dist';
const srcFolder = './src';
export const path = {
build: {
files: '${buildFolder}/files/',
},
src: {
files: '${srcFolder}/files/**/*.*',
},
watch: {
files: '${srcFolder}/files/**/*.*',
},
clean: buildFolder,
buildFolder: buildFolder,
srcFolder: srcFolder,
rootFolder: rootFolder,
ftp: ''
}
-copy.js
export const copy = () => {
return app.gulp.src(app.path.src.files)
.pipe(app.gulp.dest(app.path.build.files))
}
Your code as shared here shows that you're not using template literals properly so that gulp is trying create a folder called ${buildFolder} which is not a valid name for a folder.
This should make it work:
path.js
import * as nodePath from "path";
const rootFolder = nodePath.basename(nodePath.resolve());
const buildFolder = "./dist";
const srcFolder = "./src";
export const path = {
build: {
files: `${buildFolder}/files/`,
// ^ Note the back ticks here instead of the quotation mark
},
src: {
files: `${srcFolder}/files/**/*.*`,
// ^ Note the back ticks here instead of the quotation mark
},
watch: {
files: `${srcFolder}/files/**/*.*`,
// ^ Note the back ticks here instead of the quotation mark
},
clean: buildFolder,
buildFolder: buildFolder,
srcFolder: srcFolder,
rootFolder: rootFolder,
ftp: "",
};

Spread operator not working in Object.assign()

I'm trying to use the spread operator to populate a new object from an old object, without copying the pointer of the old object. But the new object comes out empty. :(
Here's my code:
const obj = {
a: 'a',
b: 'b',
c: 'c'
};
const test1 = Object.assign({}, ...obj);
const test2 = {};
console.log('obj', obj);
console.log('test1', test1);
console.log('test2', test2);
test1 should show up in the console with the same content as obj, but it's empty.
What am I doing wrong? Is there another way of doing it, without using Object.assign()?
(Also have this in a jsbin.)
UPDATE:
I've tried:
const test = {...obj};
But I keep getting Unexpected token on the first dot of the spread. It works in JSBin, but not on my local. So I'm thinking I may have done something wonky with Webpack or Babel.
Here's my webpack.config.js:
var path = require('path');
const DEV = process.env.NODE_ENV === 'dev';
const PROD = process.env.NODE_ENV === 'prod';
module.exports = {
devtool: 'source-map',
entry: './src/index.js',
module: {
loaders: [{
test: /\.js$/,
loaders: ['babel-loader'],
exclude: /node_modules/
},{
test: /\.(png|jpg|gif)$/,
loaders: ['url-loader'],
exclude: /node_modules/
},{
test: /\.(css|sass|scss)$/,
use: ['style-loader', 'css-loader?importLoaders=2', 'sass-loader'],
// exclude: /node_modules/
},{
test: /\.(svg)$/,
use: ['file-loader'],
// exclude: /node_modules/
},
{
test: /\.(otf)(\?.*)?$/,
loader: 'url-loader?limit=10000&mimetype=application/font-sfnt'
}]
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/dist/',
filename: 'bundle.js'
}
}
And here's my .babelrc:
{
"presets": ["env", "react"]
}
When you spread an object you need to wrap it inside an object body (same goes for arrays):
const test1 = Object.assign({}, {...obj});
With that said, i don't see any benefit from combine Object.assign with the object spread.
You could just do:
const test1 = {...obj};
Or this:
const test1 = Object.assign({}, obj);
Edit
I should mention that the object spread syntax is a proposal (in stage 3) and you need the babel plugin babel-plugin-transform-object-rest-spread to support it.
Just do:
npm install --save-dev babel-plugin-transform-object-rest-spread
And add it in your .babelrc file:
{
"plugins": ["transform-object-rest-spread"]
}
The spread operator is not properly used in this case.
You just want: Object.assign({}, obj), alternatively: test1 = { ...obj }. What you are doing is more like Object.assign({}, obj.a, obj.b, obj.c);

Trying to use request with ES6 + Webpack, but I am getting an error

I am currently trying to create a webapp with React, and I am trying to make a request to my server (with request). However, whenever I try to webpack the app I get an error. I am almost certain it has to do with request having to be labeled as an external library, but I can't get it to work. Can anybody help me?
Here is my webpack config.
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var extractCSS = new ExtractTextPlugin();
module.exports = {
entry : [
'./js/index.js'
],
output : {
path : __dirname + '/lib/',
publicPath : 'http://localhost:8080',
filename : 'bundle.js'
},
plugins : [
new ExtractTextPlugin('app.css'),
new webpack.NoErrorsPlugin()
],
module : {
loaders : [
{
test : /\.js$/,
loaders : [
'babel'
],
exclude : /node_modules/
},
{
test : /\.(jpe?g|png|gif|svg)$/i,
loaders : [
'url?limit=8192',
'img'
]
},
{
test : /\.scss$/,
include : /styles/,
loader : extractCSS.extract([
'css',
'autoprefixer',
'sass'
])
}
]
},
resolve : {
extensions : ['', '.js', '.json']
},
externals : {
request : 'request'
}
};
and here is the error that I am getting
ERROR in ./js/services/comic
Module parse failed: /Users/matthew.pfister/IdeaProjects/web/js/services/comic Line 1: Unexpected token
You may need an appropriate loader to handle this file type.
| import request from 'request';
|
| export default {
# ./js/creators/comic.js 11:21-49
Here is the file it is referencing
import request from 'request';
export default {
...
};
I dont think export default {...} is valid. try
var o = {...}
export default o
should work.
I just realized that the file that is throwing the error doesn't have the .js extension.
::facepalm:: everything is fixed.

Exposing a Javascript object as a module in webpack

Inside webpack.config.js I have computed a javascript map that I'd like import as a module in the browser. I could write the data to disk and then read it back with e.g https://github.com/webpack/json-loader, but is there any more elegant ways to do this in-memory?
webpack.config:
var config = {
key: 'data'
}
// do something with webpack loaders
some.file.that.is.executed.in.browser.js:
var config = require('config')
window.alert('Config is', config.key)
webpack loaders are file preprocessor, thus there needs to be the file that you import. So create a dummy file and use json-string-loader to override the contents.
Create an empty config.json to your project.
In webpack.config.js:
var appConfig = {
key: 'data'
}
...
loaders: [
{
test: /config.json$/,
loader: 'json-string-loader?json=' + JSON.stringify(appConfig)
}
In browser:
var appConfig = require("./config.json");
// => returns {key: 'data'}
I could write the data to disk and then read it back with e.g
https://github.com/webpack/json-loader, but is there any more elegant
ways to do this in-memory?
Why? You can just do whatever you need in config.js (instead of static json) and just return a result:
var data = 'foo' + 'bar';
module.exports = {
key: data
}

Making Grunt automatically remove files that are deleted

I use Grunt to automate converting my jade files. For that I use this script:
jade: {
compile: {
options: {
client: false,
pretty: true
},
files: [{
cwd: "_/components/jade",
src: "**/*.jade",
dest: "_/html",
expand: true,
ext: ".html"
}]
}
}
I also have this watch script running:
watch: {
jade: {
files: ['_/components/jade/**/*.jade'],
tasks: ['jade']
}
}
This works fine. However, when I delete a jade file, the html file remains. Is there a way to make grunt delete the corresponding html files when I delete a jade file?
If I understood you correctly, if you delete foo.jade you also want to delete foo.html correct? Here's an complete example using grunt-contrib-clean and grunt-contrib-watch:
You start by watching all the files with .jade extension with grunt watch. When a watched file is modified in some way, a watch event is emitted. If the event is deleted, we take the file path, change the extension to .html, set it as the src value of the clean:jade task and run the task.
module.exports = function(grunt) {
grunt.initConfig({
clean: {
jade: {
src: null
}
},
watch: {
jade: {
files: ['*.jade'],
options: {
spawn: false
}
},
}
});
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.loadNpmTasks("grunt-contrib-clean");
grunt.event.on('watch', function(action, filepath) {
if (action === "deleted") {
var file = filepath.slice(0, -5) + ".html";
grunt.config.set('clean.jade.src', [file]);
grunt.task.run("clean:jade");
}
});
};
For more information, see Using the watch event # grunt-contrib-watch. Note that spawn option must be false
If you need to dynamically modify your config, the spawn option must be disabled to keep the watch running under the same context.
You need grunt-contrib-clean. But this code clear all files of same type and make grunt slowly and require a specific config for every task. So often just use clean single time when grunt start:
module.exports = function (grunt){
grunt.initConfig({
pckg: grunt.file.readJSON('package.json'),
clean: { // Grun-contrib-clean tasks
jade: ["dist/*.html"],
all: ["dist"]
},
jade: {
dist: {
files: [{
expand: true,
cwd: 'src/templates',
src: ['**/*.jade'],
dest: 'dist',
filter: 'isFile',
ext: '.html'
}]
}
},
watch: {
jade: {
files: ['src/templates/**/*.jade'],
tasks: ['clean:jade','jade']
},
}
});
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', ['clean:all', 'jade', 'watch']);
};