I am using angular-cli in angular2 rc1 for development.
I have installed lodash node_module through npm and configured it in systemjs using following:
system.config.ts
/***********************************************************************************************
* User Configuration.
**********************************************************************************************/
/** Map relative paths to URLs. */
const map: any = {
};
/** User packages configuration. */
const packages: any = {
};
////////////////////////////////////////////////////////////////////////////////////////////////
/***********************************************************************************************
* Everything underneath this line is managed by the CLI.
**********************************************************************************************/
const barrels: string[] = [
// Angular specific barrels.
'#angular/core',
'#angular/common',
'#angular/compiler',
'#angular/http',
'#angular/router',
'#angular/platform-browser',
'#angular/platform-browser-dynamic',
'ng2-dnd',
'ng2-bootstrap',
'moment',
'lodash',
// Thirdparty barrels.
'rxjs',
// App specific barrels.
'app',
'app/shared',
/** #cli-barrel */
];
const cliSystemConfigPackages: any = {};
barrels.forEach((barrelName: string) => {
if(barrelName=='ng2-dnd'){
cliSystemConfigPackages[barrelName] = { main: 'ng2-dnd' };
}else if (barrelName == 'ng2-bootstrap') {
cliSystemConfigPackages[barrelName] = { main: 'ng2-bootstrap' };
}else if (barrelName == 'lodash') {
cliSystemConfigPackages[barrelName] = { main: 'lodash' };
}else if (barrelName == 'moment') {
cliSystemConfigPackages[barrelName] = { main: 'moment' };
}else{
cliSystemConfigPackages[barrelName] = { main: 'index' };
}
});
/** Type declaration for ambient System. */
declare var System: any;
// Apply the CLI SystemJS configuration.
System.config({
map: {
'#angular': 'vendor/#angular',
'rxjs': 'vendor/rxjs',
'main': 'main.js',
'ng2-dnd': 'vendor/ng2-dnd',
'ng2-bootstrap':'vendor/ng2-bootstrap',
'moment':'vendor/moment',
'lodash':'vendor/lodash'
},
meta: {
lodash: { format: 'amd' }
},
packages: cliSystemConfigPackages
});
// Apply the user's configuration.
System.config({ map, packages });
I would just like to note that other node_modules are working correctly i.e. moment,ng2-bootstrap etc.
angular-cli-build.js
/* global require, module */
var Angular2App = require('angular-cli/lib/broccoli/angular2-app');
module.exports = function(defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'zone.js/dist/**/*.+(js|js.map)',
'es6-shim/es6-shim.js',
'reflect-metadata/**/*.+(js|js.map)',
'rxjs/**/*.+(js|js.map)',
'#angular/**/*.+(js|js.map)',
'ng2-dnd/**/*.js',
'ng2-bootstrap/**/*.js',
'moment/*.js',
'lodash/*.js'
]
});
};
after this configuration of lodash node_module, I am importing it from the directory dist\vendors\lodash
in my app.component i am importing it as :
import _ from 'lodash';
But I am getting below error:
Cannot find module 'lodash'
any solutions?
thanks in advance
I can suggest you a workaround until they get better support for 3rd party libs. It worked for me :)
In your angular-cli-build.json , make sure it remains like this way
module.exports = function(defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
...
'lodash/**/*.js'
]
});
};
and in your system-config.ts:
/** Map relative paths to URLs. */
const map: any = {
'lodash': 'vendor/lodash/lodash.js'
};
/** User packages configuration. */
const packages: any = {
'lodash': {
format: 'cjs'
}
};
in your src/index.html add this line
<script src="/vendor/lodash/lodash.js" type="text/javascript"></script>
now in your component where you want to use lodash , write this way
declare var _:any;
#Component({
})
export class YourComponent {
ngOnInit() {
console.log(_.chunk(['a', 'b', 'c', 'd'], 2));
}
}
Try using:
import * as _ from 'lodash';
Related
I really need someone's help.
In this repo,
https://github.com/ueno-llc/starter-kit-universally.git
I don't know how to upgrade the webpack.
The error is from new webpack.NamedChunksPlugin, new webpack.optimize.CommonsChunkPlugin
I can't fix it by myself...
Can anyone help me for this issue ?
import fs from 'fs';
import _isArray from 'lodash/isArray';
import _get from 'lodash/get';
import appRootDir from 'app-root-dir';
import path from 'path';
import webpack from 'webpack';
import ExtractCssChunks from 'extract-css-chunks-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import ChunkManifestWebpackPlugin from 'chunk-manifest-webpack-plugin';
import NameAllModulesPlugin from 'name-all-modules-plugin';
import config from '../';
import { removeNil } from '../../internal/utils/arrays';
import { ifElse } from '../../internal/utils/logic';
function externals() {
// UENO: Define externals
// We don't want our node_modules to be bundled with any bundle that is
// targetting the node environment, prefering them to be resolved via
// native node module system.
// Some of our node_modules may contain files that depend on our
// webpack loaders, e.g. CSS or SASS.
// For these cases please make sure that the file extensions are
// registered within the following configuration setting.
const whitelist = [
/\.bin/,
'source-map-support/register',
'react-universal-component',
'webpack-flush-chunks',
]
// And any items that have been whitelisted in the config need
// to be included in the bundling process too.
.concat(config('nodeExternalsFileTypeWhitelist') || []);
return fs
.readdirSync(path.resolve(appRootDir.get(), 'node_modules'))
.filter(x => !whitelist.some((w) => {
if (w instanceof RegExp) {
return w.test(x);
}
return x === w;
}))
.reduce((ext, mod) => {
// mark this module as external
// https://webpack.js.org/configuration/externals
ext[mod] = `commonjs ${mod}`;
return ext;
}, {});
}
export default (webpackConfig, buildOptions) => {
const { target, optimize = false, localIdentName } = buildOptions;
const isProd = optimize;
const isDev = !isProd;
const isClient = target === 'client';
const isNode = !isClient;
const ifNode = ifElse(isNode);
const ifClient = ifElse(isClient);
const ifProdClient = ifElse(isProd && isClient);
// Overwrite the externals because apparently `webpack-node-externals` does not
// work well with `webpack-flush-chunks`
if (isNode) {
webpackConfig.externals = [externals()];
}
// Remove ExtractTextPlugin
const etpIndex = webpackConfig.plugins.findIndex(p => p instanceof ExtractTextPlugin);
if (etpIndex > -1) {
webpackConfig.plugins.splice(etpIndex, 1);
}
// Add some plugins for css code splitting
webpackConfig.plugins.push(
...removeNil([
// NamedModulesPlugin, NamedChunksPlugin and NameAllModulesPlugin (see below) are all here to
// deal with chunk hashes.
// See https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31
ifClient(new webpack.NamedModulesPlugin()),
ifClient(
new webpack.NamedChunksPlugin((chunk) => {
if (chunk.name) {
return chunk.name;
}
return chunk.mapModules(m => path.relative(m.context, m.request)).join('_');
}),
),
ifClient(new ExtractCssChunks({
filename: isDev ? '[name].js' : '[name]-[contenthash].css',
})),
ifProdClient(new ChunkManifestWebpackPlugin({
filename: '../manifest.json',
manifestVariable: '__WEBPACK_MANIFEST__',
})),
// To make sure chunk hashes stay the same if their contents don’t change
// see: https://webpack.js.org/guides/caching/#module-identifiers
ifClient(new webpack.HashedModuleIdsPlugin()),
// Add vendor code chunk
ifProdClient(
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: '[name]-[chunkhash].js',
// Put all node_modules into one chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#passing-the-minchunks-property-a-function
minChunks: module => module.context && module.context.includes('node_modules'),
}),
),
// Add webpack boilerplate chunk
ifClient(
new webpack.optimize.CommonsChunkPlugin({
name: 'bootstrap', // needed to put webpack bootstrap code before chunks
filename: isDev ? '[name].js' : '[name]-[chunkhash].js',
}),
),
ifClient(new NameAllModulesPlugin()),
// We only want one server chunk
ifNode(
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
),
]),
);
const { rules } = webpackConfig.module;
const moduleRules = [..._get(rules, '0.oneOf', rules)];
// Overwrite css loader ExtractTextPlugin
const cssRule = moduleRules.find(r => r.test.test('.css'));
if (cssRule && _isArray(cssRule.use)) {
// Find plugin
const pluginIndex = cssRule.use.findIndex(u =>
Object.prototype.hasOwnProperty.call(u, 'loader') && /extract-text-webpack-plugin/.test(u.loader));
if (pluginIndex > -1) {
const loaders = ExtractCssChunks.extract({
fallback: 'style-loader',
use: [
`css-loader?modules=1&importLoaders=1&localIdentName=${localIdentName}`,
'postcss-loader',
'sass-loader?outputStyle=expanded',
],
});
cssRule.use.splice(
pluginIndex,
loaders.length,
...loaders,
);
}
}
// Overwrite node_modules css loader ExtractTextPlugin
const nmCssRule = moduleRules.find(r =>
r.test.test('node_modules.css') &&
(!r.exclude || !r.exclude.test('node_modules.css')));
if (nmCssRule && _isArray(nmCssRule.use)) {
// Find plugin
const pluginIndex = nmCssRule.use.findIndex(u =>
Object.prototype.hasOwnProperty.call(u, 'loader') && /extract-text-webpack-plugin/.test(u.loader));
if (pluginIndex > -1) {
const loaders = ExtractCssChunks.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader'],
});
nmCssRule.use.splice(
pluginIndex,
loaders.length,
...loaders,
);
}
}
return webpackConfig;
};
===
I have tried to use webpack.config.js, but still failed...
Please help me :(
Basically what I need is generate one single file that contain all vendors and dependencies for each entry..
export default defineConfig({
plugins: [ react() ],
build: {
rollupOptions: {
input: {
popup: path.resolve(pagesDirectory, 'popup', 'index.html'),
background: path.resolve(pagesDirectory, 'background', 'index.ts'),
content_script: path.resolve(pagesDirectory, 'content_script', 'ContentScript.tsx')
},
output: {
entryFileNames: 'src/pages/[name]/index.js',
chunkFileNames: isDevelopment ? 'assets/js/[name].js' : 'assets/js/[name].[hash].js',
assetFileNames: (assetInfo) => {
const { dir, name: _name } = path.parse(assetInfo.name);
const assetFolder = getLastElement(dir.split('/'));
const name = assetFolder + firstUpperCase(_name);
return `assets/[ext]/${name}.chunk.[ext]`;
}
}
}
}})
In this case.. will be one file for popup, background and content_script
Here is one example of ContentScript.tsx file...
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import Badge from './badge';
function init(query: string) {
const appContainer = document.querySelector('#search') as HTMLElement;
if (!appContainer) {
throw new Error('Can not find AppContainer');
}
const rootElement = document.createElement('div');
rootElement.setAttribute('id', 'web-answer-content-script');
appContainer.insertBefore(rootElement, appContainer.firstChild);
const root = createRoot(rootElement, {});
root.render(
<React.StrictMode>
<Badge query={query} />
</React.StrictMode>
);
}
const searchParameters = new URLSearchParams(window.location.search);
if (searchParameters.has('q')) {
const query = searchParameters.get('q');
init(query);
}
import MessageSender = chrome.runtime.MessageSender;
function handleMessageReceived(message: string, sender: MessageSender) {
console.log('>>> MESSAGE RECEIVED', message, sender);
}
chrome.runtime.onMessage.addListener(handleMessageReceived);
With this configuration I'm getting this..
and my content_scripts/index.js ..
import { j as n, c as a, r as c } from '../../../assets/jsx-dev-runtime.a077470a.js';
// ..rest of the code...
As you can see.. I don't want this import... statement ..
On react app, you can create .env.production and .env.development and enter different key and values like this.
REACT_APP_API_URL= "xyz"
to pick environment variables automatically based on commands used --> npm start or npm run build.
What is the equivalent process in preact?
It is my solution
env.js in the root of project:
import fs from 'fs';
import dotenv from 'dotenv';
function getAppEnvironment() {
const prefix = "PREACT";
return Object.keys(process.env)
.filter((key) => new RegExp(`^${prefix}_`, 'i').test(key))
.reduce((env, key) => {
env[key] = process.env[key];
return env;
}, {});
}
function resolveFile(file) {
const path = fs.realpathSync(process.cwd());
return `${path}/${file}`;
}
function getEnvFiles(production) {
const key = production ? 'production' : 'development';
return [
resolveFile(".env"),
resolveFile(".env.local"),
resolveFile(`.env.${key}`),
resolveFile(`.env.${key}.local`),
].filter(Boolean);
}
export function getEnvironment(production) {
const dotenvFiles = getEnvFiles(production);
dotenvFiles.forEach((dotenvFile) => {
if (fs.existsSync(dotenvFile)) {
dotenv.config({
path: dotenvFile,
override: true
})
}
});
return getAppEnvironment();
}
export default getEnvironment;
then create or modify your preact.config.js:
import getEnvironment from './env';
export default {
plugins: [],
webpack(config, env, helpers) {
config.plugins.push(
new helpers.webpack.DefinePlugin({
'process.env': JSON.stringify(getEnvironment(env.production))
}),
);
},
};
I'm starting out with vue and nuxt, I have a project using vuetify and I'm trying to modify the carousel component to dynamically load images from the static folder. So far I've come up with:
<template>
<v-carousel>
<v-carousel-item v-for="(item,i) in items" :key="i" :src="item.src"></v-carousel-item>
</v-carousel>
</template>
<script>
function getImagePaths() {
var glob = require("glob");
var options = {
cwd: "./static"
};
var fileNames = glob.sync("*", options);
var items = [];
fileNames.forEach(fileName =>
items.push({
'src': '/'+fileName
})
);
return items;
}
export default {
data() {
return {items :getImagePaths()};
}
};
</script>
When I test this I see:
ERROR in ./node_modules/fs.realpath/index.js
Module not found: Error: Can't resolve 'fs' in '....\node_modules\fs.realpath'
ERROR in ./node_modules/fs.realpath/old.js
Module not found: Error: Can't resolve 'fs' in ....\node_modules\fs.realpath'
ERROR in ./node_modules/glob/glob.js
Module not found: Error: Can't resolve 'fs' in '....\node_modules\glob'
ERROR in ./node_modules/glob/sync.js
Module not found: Error: Can't resolve 'fs' in '.....\node_modules\glob'
googling this I see a bunch of references like https://github.com/webpack-contrib/css-loader/issues/447.
These suggest that you have to midify the webpack config file with something like:
node: {
fs: 'empty'
}
I know very little about webpack. I found https://nuxtjs.org/faq/extend-webpack/ , but am not sure how to modify the webpack config file in this case.
How do I do this?
You can't use NodeJs specific module on browser.
To solve your issue, you can create an API using Nuxt server middleware. The code below, inspired by https://github.com/nuxt-community/express-template.
Create a file, index.js in api/index.js. Then fill it with:
const express = require('express')
// Create express instance
const app = express()
// Require API routes
const carousel = require('./routes/carousel')
// Import API Routes
app.use(carousel)
// Export the server middleware
module.exports = {
path: '/api',
handler: app
}
Create carousel.js in api/routes/carousel.js. Then fill it with:
const { Router } = require('express')
const glob = require('glob')
const router = Router()
router.get('/carousel/images', async function (req, res) {
const options = {
cwd: './static'
}
const filenames = glob.sync('*', options)
let items = [];
filenames.forEach(filename =>
items.push({
'src': '/'+filename
})
);
return res.json({ data: items })
})
module.exports = router
Register your server middleware in nuxt.config.js
module.exports = {
build: {
...
},
serverMiddleware: [
'~/api/index.js'
]
}
Call the api in your page / component. I assume you're using Axios here (axios-module).
<script>
export default {
async asyncData ({ $axios }) {
const images = (await $axios.$get('/api/carousel/images')).data
return { images }
}
}
</script>
I know this is an old question, but it may be helpful for someone to disable fs in their browser.
Like this:
nuxt.config.js
build: {
extend (config, { isDev, isClient }) {
config.node= {
fs: 'empty'
}
// ....
}
},
Add this in your nuxt-config.js:
build: { extend (config, { isDev, isClient }) {
config.node = {
fs: 'empty'
}
// ....
}},
I'm trying to set up assetmanager
for my blog that has three modules
default
login
admin
I tried like
assets.json
{
"css": {
"app":{
"public/src/dist/default/css/dist.min.css": [
"public/src/assets/default/css/*.css"
]
},
"login":{
"public/src/dist/login/css/dist.min.css": [
"public/src/assets/default/css/*.css"
]
},
"admin":{
"public/src/dist/admin/css/dist.min.css": [
"public/src/assets/admin/css/*.css"
]
}
}
}
express.js
assetmanager.init({
js: assets.js,
css: assets.css,
debug: (process.env.NODE_ENV !== 'production'),
webroot: 'public'
});
// Add assets to local variables
app.use(function(req, res, next) {
res.locals({
assets: assetmanager.assets
});
next();
});
console.log(assetmanager.assets);
but console.log(assetmanager.assets);
give me a empty array []
so is there a way to manage assetmanager
with more than one module ?
the best way I found up to now
is like in my controllers:
'use strict';
var assetmanager = require('assetmanager');
exports.render = function(config) {
var assets = require(config.sroot+'/config/assets.json');
assetmanager.init({
js: assets.js.app,
css: assets.css.app,
debug: (process.env.NODE_ENV !== 'production'),
webroot: 'public'
});
return function(req, res) {
res.render('layouts/default', {appTitle:'ilwebdifabio',assets:assetmanager.assets});
}
};
but it's quite ugly and I have
duplicate code :(
END UP
There is no way to use assetmanager module
in different modules (login,default,admin).
Modules are automatically cached by the Node.js application upon first load. As such, repeated calls to require() - the global method that loads modules - will all result in a reference to the same cached object.
so you end up ie if you use in a module
to the have the dedicate assets in all other module so
I worked it out with :
'use strict';
var _ = require('lodash');
module.exports = function (path,route) {
var env = (process.env.NODE_ENV === 'production') ? 'production' : null;
var debug = (env !== 'production');
var data = require(path+'/config/assets.json');
var assets = {
css: [],
js: []
};
var getAssets = function (pattern) {
var files = [];
if (_.isArray(pattern)) {
_.each(pattern, function (path) {
files = files.concat(getAssets(path));
});
} else if (_.isString(pattern)) {
var regex = new RegExp('^(//)');
if (regex.test(pattern)) {
// Source is external
//For the / in the template against 404
files.push(pattern.substring(1));
} else {
files.push(pattern);
}
}
return files;
};
var getFiles = function () {
var current = data[route];
_.each(['css', 'js'], function (fileType) {
_.each(current[fileType], function (value, key) {
if (!debug) {
assets[fileType].push(key);
} else {
assets[fileType] = assets[fileType].concat(getAssets(value));
}
});
});
};
var getCurrentAssets = function(){
return assets;
};
getFiles();
return {
getCurrentAssets: getCurrentAssets
};
};
in the controller
var assetmanager = require(config.sroot+'/utils/assetsmanager')(config.sroot,'app');
res.render('layouts/default', {
assets:assetmanager.getCurrentAssets()
});
There is a new version of assetmanager 1.0.0 that I believe accomplishes what you're trying to do more effectively. In the new version you can break apart your assets into groups so that you can support multiple layouts. The github has a complete example here but essentially your asset files ends up looking something like this:
{
"main": {
"css": {
"public/build/css/main.min.css": [
"public/lib/bootstrap/dist/css/bootstrap.css",
"public/css/**/*.css"
]
},
"js": {
"public/build/js/main.min.js": [
"public/lib/angular/angular.js",
"public/js/**/*.js"
]
}
},
"secondary": {
"css": {
"public/build/css/secondary.min.css": [
"public/css/**/*.css"
]
},
"js": {
"public/build/js/secondary.min.js": [
"public/js/**/*.js"
]
}
}
}
And then in your layouts you just include the group you want. Hopefully that helps out.