NPM Workspaces monorepo - share local package's distribution folder as root instead of the entire source files - npm

Using NPM Workspaces, I'm sharing one package (components) with others (webapp1 and webapp2). Something like this:
root
apps
webapp1
webapp2
packages
components
Everything is working well, but everything inside components, include source code in the src folder is being shared. Since components' compiled output folder is dist, I'd like to only share that folder. This is how it looks in the root node_modules:
The problem is that when I need to import in webapp1 or webapp2, my import path has to include the dist folder. Here's the intellisense that I get from VS Code:
And this is how I import in webapp1 and webapp2:
import Center from '#mycompany/components/dist/Center'
While everything works, how can I set up my NPM Workspaces so that only the contents of the dist folder is shared in its root?
I've tried NPM's files and .npmignore inside the components folder to ignore everything except for the dist folder, but that doesn't seem to work. The main property in package.json for components is also set to point to dist/index.js:
"main": "dist/index.js"
Interestingly, if I want to import dist/index.js file, I can do it without dist:
import foo from '#mycompany/components'
...however, importing anything other than dist/index.js requires dist to be included in the path.

You should treat the packages folder as a collection of dist folders in your use case.
In this scenario, you would move your packages/components/src folder somewhere else in your project and then build to packages/components instead of packages/components/dist
root
apps
webapp1
webapp2
packages
components
src
components
I have a similar setup in this tooling monorepo I created

An alternative to #nicksaroba's approach, if you don't want to restructure your project layout, you can just setup an alias:
// apps/webapp/webpack.config.js
module.exports = {
// ...
resolve: {
alias: {
"components": "#mycompany/components/dist/"
}
},
// ...
};

Related

How can I serve static file using #nrwl/express

I am using nx to manage my work environment with #nrwl/express plugin. I want to serve static file from the express server but with no success.
I tried the following.
express.static(path.join(__dirname, 'videos'));
but I am not able to get the files inside the videos directory, I always get 404.
I tried both this URLs
http://localhost:3333/api/output.m3u8
http://localhost:3333/output.m3u8
the videos directory is located in the root of my app.
Any idea how can I solve this?
Not sure if you ever solved this but I've just ran into the same problem myself.
When you serve your Express App with Nx it will be transpiled and served from the dist folder. Therefore __dirname will actually resolve to your monoreporoot/dist folder (i.e. the root of your project /dist).
If like me you were trying to serve content from a static folder inside your src directory or similar, you will need to ensure that it's transferred across to your dist folder when serving your Express app.
For me, it wasn't a problem as I was just using it as a temporary upload folder for dev so I manually created the folder inside of dist. If it's linked to your app then you might need to add a specific mkdir or cp command to your build to make sure the files/folder is present.
The process of using from the dist folder, so it is necessary that the source folder be copied.
Add a line to project.json
{
"targets": {
"build": {
"executor": "#nrwl/node:webpack",
"outputs": ["{options.outputPath}"],
"options": {
...
"assets": ["packages/<your-app>/src/public"] <-- need add this line
},
"configurations": {
...
}
}
}
Add this in your main.ts
app.use('/static', express.static(__dirname + '/public'));
The file in packages/[your-app]/src/public/some-file.txt will be available at
http://localhost:3333/static/some-file.txt

Change default directory in Snowpack Vue app

I want to use Snowpack for my Vue 3 app. Currently, I've initialized the Vue 3 app using the following command:
npx create-snowpack-app my-app --template #snowpack/app-template-vue
By default, Snowpack creates a directory structure like this:
public/
src/
App.vue
index.js
package.json
README.md
snowpack.config.js
I need to restructure things slightly. The reason why is I'm moving an existing app to Snowpack. My challenge is I need to move to a structure like this:
public/
pages/
App.vue
index.js
package.json
README.md
snowpack.config.js
In short: 1) rename src to pages and 2) move index.js up to the same level as package.json. When I make this change, Snowpack throws a warning that says "mounted directory does not exist". It prints out the files it's looking for, which, Snowpack is clearly still looking in the src directory. My thinking was to review the snowpack.config.js file.
I looked at the mount property in the snowpack.config.js file. I changed mount.src.url to /pages. However, that didn't work. I also tried changing the property to just /, which also didn't work.
What do I need to change to tell Snowpack to look in the current directory instead of the src directory for the index.js file?
That directory layout is possible with a mount config that specifies . as the mount point:
// snowpack.config.js
module.exports = {
mount: {
'.': {url: '/dist'}
},
}
Then the root index could import the SFC from <projectRoot>/pages/:
// <projectRoot>/index.js
import App from './pages/App.vue'
...

Can I select which files will be compiled in webpack or vueloader while building?

When I build my Vue project with npm run build, I would like to choose particular Vue files to be (re)compiled into the dist folder. My idea was by changing the configurations in webpack or the webpack-chain to compile from a specific entry point. An example of my goal would be:
Let's assume I have 2 components; A.vue and B.vue (and ofcourse the default files like index.html etc.)
Then I build the project, which gives me a ./dist folder with everything compiled. Then after I make changes to B.vue (and change the config file most likely), I only want B.vue to be recompiled into the ./dist folder. I already use dynamic imports so that A.vue and B.vue are different bundles, so that other files should not have to be changed.
Can I select a specific file to be compiled only?
(I am aware that the dist folder gets emptied after building, but that I will try to fix later if this could be possible)
I think you're looking for watch mode: npm run build --watch

How can I import an external file without it being built in the webpack?

I am configuring my infrastructure to run an application vue.
I have two folders vue_lab and vue_prod
I want to create a config.js file in the project root and add this file in .gitignore.
Inside this file I'll put the api url.
I need this file not to be built when running npm run build.
I could use .env.production but the problem is that I have two production environments (lab and prod) and I need to have a different env file in each project.
I tried to create a file config.js at the root of the project:
export const API_HOST = 'http://www.url.com.br';
inside the component I import the file and use the variable:
import {API_HOST} from '../config';
the problem is that when running the npm run build command the config.js file is built in the webpack and I can not put it in gitignore. How can I import an external file without it being built in the webpack?
If your concern about using .env files is supporting multiple environments, you can actually configure which .env.* file you want to use, with something like this:
import dotenv from 'dotenv';
import path from 'path';
dotenv.config({ path: path.resolve(__dirname, ./.env.${process.env.ENVIRONMENT})});
You probably have to tweak the snippet above a little bit depending on how you configure webpack.

Managing Dependencies in SailsJS

How can I manage dependencies in a Sails.JS based project. There is a really neat feature which automatically links assets from the assets folder into the relevant templates, however, to get these files, e.g Angular, Bootstrap, Material-Design etc. I like to run bower / npm install. But then the resources are in the bower_compnents file and can't be linked to. How can I work around this to get file installed by package managers to be included in Sails.JS's default mechanism?
You have the option to change the location of the bower components with a .bower.rc file.
Example .bower.rc
{
"directory": "assets/components/"
}
It is not a good idea to automatically link components, there are many .js/.css files that must not included together (eg. lib_name.js and lib_name.min.js).
You have to include them manually like this (tasks/pipeline.js)
var jsFilesToInject = [
'components/lodash/lodash.js',
'components/moment/moment.js',
'components/moment/locale/el.js',
'components/angular-moment/angular-moment.js',
'components/re-tree/re-tree.min.js',
'components/ng-device-detector/ng-device-detector.js',
// Load sails.io before everything else
'js/dependencies/extend.js',
'js/dependencies/sails.io.js',
// Dependencies
//'js/dependencies/**/*.js',
'js/my-app-bootstrap.js',
// load my controllers
'js/angular/**/*.js',
'js/my-app.js',
];