Skip to content

Commit 0e53810

Browse files
committed
feat: add support for configuring encore
1 parent 7d9aa0a commit 0e53810

File tree

3 files changed

+298
-0
lines changed

3 files changed

+298
-0
lines changed

commands/Invoke.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* file that was distributed with this source code.
88
*/
99

10+
import { join } from 'path'
1011
import { BaseCommand, args } from '@adonisjs/core/build/standalone'
1112
import { Manifest } from '../src/Manifest'
1213

@@ -26,10 +27,57 @@ export default class Configure extends BaseCommand {
2627
})
2728
public name: string
2829

30+
/**
31+
* Configure encore
32+
*/
33+
private async configureEncore() {
34+
const { files, logger } = await import('@adonisjs/sink')
35+
36+
/**
37+
* Create the webpack config file
38+
*/
39+
const webpackConfigFile = new files.MustacheFile(
40+
this.application.appRoot,
41+
'webpack.config.js',
42+
join(__dirname, '..', 'templates/webpack.config.txt')
43+
)
44+
if (!webpackConfigFile.exists()) {
45+
webpackConfigFile.apply({}).commit()
46+
logger.action('create').succeeded('webpack.config.js')
47+
}
48+
49+
/**
50+
* Create app.js entrypoint
51+
*/
52+
const entryPointFile = new files.NewLineFile(this.application.appRoot, 'resources/js/app.js')
53+
if (!entryPointFile.exists()) {
54+
entryPointFile.add('// app entrypoint').commit()
55+
logger.action('create').succeeded('resources/js/app.js')
56+
}
57+
58+
const pkgFile = new files.PackageJsonFile(this.application.appRoot)
59+
pkgFile.install('@symfony/webpack-encore')
60+
61+
const spinner = logger.await(logger.colors.gray('installing @symfony/webpack-encore'))
62+
63+
try {
64+
await pkgFile.commitAsync()
65+
spinner.update('Installed')
66+
} catch (error) {
67+
spinner.update('Unable to install the package')
68+
logger.fatal(error)
69+
}
70+
}
71+
2972
/**
3073
* Invoked automatically by ace
3174
*/
3275
public async run() {
76+
if (this.name === 'encore') {
77+
await this.configureEncore()
78+
return
79+
}
80+
3381
const { tasks } = await import('@adonisjs/sink')
3482

3583
await new tasks.Instructions(

templates/webpack.config.txt

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
const { join } = require('path')
2+
const Encore = require('@symfony/webpack-encore')
3+
4+
/*
5+
|--------------------------------------------------------------------------
6+
| Encore runtime environment
7+
|--------------------------------------------------------------------------
8+
*/
9+
if (!Encore.isRuntimeEnvironmentConfigured()) {
10+
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev')
11+
}
12+
13+
/*
14+
|--------------------------------------------------------------------------
15+
| Output path
16+
|--------------------------------------------------------------------------
17+
|
18+
| The output path for writing the compiled files. It should always
19+
| be inside the public directory, so that AdonisJS can serve it.
20+
|
21+
*/
22+
Encore.setOutputPath('./public/assets')
23+
24+
/*
25+
|--------------------------------------------------------------------------
26+
| Public URI
27+
|--------------------------------------------------------------------------
28+
|
29+
| The public URI to access the static files. It should always be
30+
| relative from the "public" directory.
31+
|
32+
*/
33+
Encore.setPublicPath('/assets')
34+
35+
/*
36+
|--------------------------------------------------------------------------
37+
| Entrypoints
38+
|--------------------------------------------------------------------------
39+
|
40+
| Entrypoints are script files that boots your frontend application. Ideally
41+
| a single entrypoint is used by majority of applications. However, feel
42+
| free to add more (if required).
43+
|
44+
| Also, make sure to read the docs on "Assets bundler" to learn more about
45+
| entrypoints.
46+
|
47+
*/
48+
Encore.addEntry('app', './resources/js/app.js')
49+
50+
/*
51+
|--------------------------------------------------------------------------
52+
| Copy assets
53+
|--------------------------------------------------------------------------
54+
|
55+
| Since the edge templates are not part of the Webpack compile lifecycle, any
56+
| images referenced by it will not be processed by Webpack automatically. Hence
57+
| we must copy them manually.
58+
|
59+
*/
60+
// Encore.copyFiles({
61+
// from: './resources/images',
62+
// to: 'images/[path][name].[hash:8].[ext]',
63+
// })
64+
65+
/*
66+
|--------------------------------------------------------------------------
67+
| Split shared code
68+
|--------------------------------------------------------------------------
69+
|
70+
| Instead of bundling duplicate code in all the bundles, generate a separate
71+
| bundle for the shared code.
72+
|
73+
| https://symfony.com/doc/current/frontend/encore/split-chunks.html
74+
| https://webpack.js.org/plugins/split-chunks-plugin/
75+
|
76+
*/
77+
Encore.splitEntryChunks()
78+
79+
/*
80+
|--------------------------------------------------------------------------
81+
| Isolated entrypoints
82+
|--------------------------------------------------------------------------
83+
|
84+
| Treat each entry point and its dependencies as its own isolated module.
85+
|
86+
*/
87+
Encore.disableSingleRuntimeChunk()
88+
89+
/*
90+
|--------------------------------------------------------------------------
91+
| Cleanup output folder
92+
|--------------------------------------------------------------------------
93+
|
94+
| It is always nice to cleanup the build output before creating a build. It
95+
| will ensure that all unused files from the previous build are removed.
96+
|
97+
*/
98+
Encore.cleanupOutputBeforeBuild()
99+
100+
/*
101+
|--------------------------------------------------------------------------
102+
| Source maps
103+
|--------------------------------------------------------------------------
104+
|
105+
| Enable source maps in production
106+
|
107+
*/
108+
Encore.enableSourceMaps(!Encore.isProduction())
109+
110+
/*
111+
|--------------------------------------------------------------------------
112+
| Assets versioning
113+
|--------------------------------------------------------------------------
114+
|
115+
| Enable assets versioning to leverage lifetime browser and CDN cache
116+
|
117+
*/
118+
Encore.enableVersioning(Encore.isProduction())
119+
120+
/*
121+
|--------------------------------------------------------------------------
122+
| Configure dev server
123+
|--------------------------------------------------------------------------
124+
|
125+
| Here we configure the dev server to enable live reloading for edge templates.
126+
| Remember edge templates are not processed by Webpack and hence we need
127+
| to watch them explicitly and livereload the browser.
128+
|
129+
*/
130+
Encore.configureDevServerOptions((options) => {
131+
/**
132+
* Normalize "options.static" property to an array
133+
*/
134+
if (!options.static) {
135+
options.static = []
136+
} else if (!Array.isArray(options.static)) {
137+
options.static = [options.static]
138+
}
139+
140+
/**
141+
* Enable live reload and add views directory
142+
*/
143+
options.liveReload = true
144+
options.static.push({
145+
directory: join(__dirname, './resources/views'),
146+
watch: true,
147+
})
148+
})
149+
150+
/*
151+
|--------------------------------------------------------------------------
152+
| CSS precompilers support
153+
|--------------------------------------------------------------------------
154+
|
155+
| Uncomment one of the following lines of code to enable support for your
156+
| favorite CSS precompiler
157+
|
158+
*/
159+
// Encore.enableSassLoader()
160+
// Encore.enableLessLoader()
161+
// Encore.enableStylusLoader()
162+
163+
/*
164+
|--------------------------------------------------------------------------
165+
| CSS loaders
166+
|--------------------------------------------------------------------------
167+
|
168+
| Uncomment one of the following line of code to enable support for
169+
| PostCSS or CSS.
170+
|
171+
*/
172+
// Encore.enablePostCssLoader()
173+
// Encore.configureCssLoader(() => {})
174+
175+
/*
176+
|--------------------------------------------------------------------------
177+
| Configure logging
178+
|--------------------------------------------------------------------------
179+
|
180+
| To keep the terminal clean from unnecessary info statements , we only
181+
| log warnings and errors. If you want all the logs, you can change
182+
| the level to "info".
183+
|
184+
*/
185+
const config = Encore.getWebpackConfig()
186+
config.infrastructureLogging = {
187+
level: 'warn',
188+
}
189+
config.stats = 'errors-warnings'
190+
191+
/*
192+
|--------------------------------------------------------------------------
193+
| Export config
194+
|--------------------------------------------------------------------------
195+
|
196+
| Export config for webpack to do its job
197+
|
198+
*/
199+
module.exports = config

test/configure-encore.spec.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* @adonisjs/assembler
3+
*
4+
* (c) Harminder Virk <[email protected]>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
import test from 'japa'
11+
import { join } from 'path'
12+
import { Kernel } from '@adonisjs/ace'
13+
import { Filesystem } from '@poppinss/dev-utils'
14+
import { Application } from '@adonisjs/application'
15+
16+
import Invoke from '../commands/Invoke'
17+
18+
const fs = new Filesystem(join(__dirname, '__app'))
19+
20+
test.group('Configure Encore', (group) => {
21+
group.afterEach(async () => {
22+
await fs.cleanup()
23+
})
24+
25+
test
26+
.skipInCI('setup encore', async (assert) => {
27+
await fs.add(
28+
'package.json',
29+
JSON.stringify({
30+
name: 'sample_app',
31+
})
32+
)
33+
34+
await fs.ensureRoot()
35+
const app = new Application(fs.basePath, 'test', {})
36+
37+
const invoke = new Invoke(app, new Kernel(app))
38+
invoke.name = 'encore'
39+
await invoke.run()
40+
41+
const envFile = await fs.fsExtra.pathExists(join(fs.basePath, 'webpack.config.js'))
42+
const envExampleFile = await fs.fsExtra.readFile(
43+
join(fs.basePath, 'resources/js/app.js'),
44+
'utf-8'
45+
)
46+
47+
assert.isTrue(envFile)
48+
assert.equal(envExampleFile.trim(), '// app entrypoint')
49+
})
50+
.timeout(0)
51+
})

0 commit comments

Comments
 (0)