mirror of
https://github.com/strapi/strapi.git
synced 2025-08-12 18:53:23 +00:00
Merge branch 'master' into patch-1
This commit is contained in:
commit
8ba1c1f51a
@ -156,7 +156,7 @@ Before submitting an issue you need to make sure:
|
||||
- You have tried all the following (if relevant) and your issue remains:
|
||||
- Make sure you have the right application started.
|
||||
- Make sure the [issue template](.github/ISSUE_TEMPLATE) is respected.
|
||||
- Make sure your issue body is readable and [well formated](https://guides.github.com/features/mastering-markdown).
|
||||
- Make sure your issue body is readable and [well formatted](https://guides.github.com/features/mastering-markdown).
|
||||
- Make sure you've killed the Strapi server with CTRL+C and started it again.
|
||||
- Make sure the application you are using to reproduce the issue has a clean `node_modules` directory, meaning:
|
||||
- no dependencies are linked (e.g. you haven't run `npm link`)
|
||||
|
@ -124,10 +124,12 @@ module.exports = {
|
||||
collapsable: true,
|
||||
title: '📚 Guides',
|
||||
children: [
|
||||
'/3.0.0-beta.x/guides/update-version',
|
||||
'/3.0.0-beta.x/guides/databases',
|
||||
'/3.0.0-beta.x/guides/deployment',
|
||||
'/3.0.0-beta.x/guides/jwt-validation',
|
||||
'/3.0.0-beta.x/guides/error-catching',
|
||||
'/3.0.0-beta.x/guides/slug',
|
||||
'/3.0.0-beta.x/guides/webhooks',
|
||||
],
|
||||
},
|
||||
|
BIN
docs/3.0.0-beta.x/assets/guides/slug/fields.png
Normal file
BIN
docs/3.0.0-beta.x/assets/guides/slug/fields.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-after.png
Normal file
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-after.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-before.png
Normal file
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-before.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-config.png
Normal file
BIN
docs/3.0.0-beta.x/assets/guides/slug/layout-config.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 107 KiB |
@ -66,7 +66,7 @@ Here are some use cases:
|
||||
- Create an admin user if there isn't one.
|
||||
- Fill the database with some necessary data.
|
||||
- Check that the database is up-and-running.
|
||||
- Load some envrionments variables.
|
||||
- Load some environments variables.
|
||||
|
||||
The bootstrap function can be synchronous or asynchronous
|
||||
|
||||
|
@ -4,48 +4,50 @@
|
||||
|
||||
Models are a representation of the database's structure and lifecycle. They are split into two separate files. A JavaScript file that contains the lifecycle callbacks, and a JSON one that represents the data stored in the database and their format. The models also allow you to define the relationships between them.
|
||||
|
||||
**Path —** `./api/user/models/User.js`.
|
||||
**Path —** `./api/restaurant/models/Restaurant.js`.
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
// Before saving a value.
|
||||
// Fired before an `insert` or `update` query.
|
||||
beforeSave: next => {
|
||||
// Use `this` to get your current object
|
||||
next();
|
||||
},
|
||||
beforeSave: (model, attrs, options) => {},
|
||||
|
||||
// After saving a value.
|
||||
// Fired after an `insert` or `update` query.
|
||||
afterSave: (doc, next) => {
|
||||
next();
|
||||
},
|
||||
afterSave: (model, attrs, options) => {},
|
||||
|
||||
// ... and more
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/user/models/User.settings.json`.
|
||||
**Path —** `./api/restaurant/models/Restaurant.settings.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"connection": "default",
|
||||
"info": {
|
||||
"name": "user",
|
||||
"description": "This represents the User Model"
|
||||
"name": "restaurant",
|
||||
"description": "This represents the Restaurant Model"
|
||||
},
|
||||
"attributes": {
|
||||
"firstname": {
|
||||
"cover": {
|
||||
"collection": "file",
|
||||
"via": "related",
|
||||
"plugin": "upload"
|
||||
},
|
||||
"name": {
|
||||
"default": "",
|
||||
"type": "string"
|
||||
},
|
||||
"lastname": {
|
||||
"type": "string"
|
||||
"description": {
|
||||
"default": "",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this example, there is a `User` model which contains two attributes `firstname` and `lastname`.
|
||||
In this example, there is a `Restaurant` model which contains two attributes `cover`, `name` and `description`.
|
||||
|
||||
### Where are the models defined?
|
||||
|
||||
@ -57,12 +59,12 @@ The models are defined in each `./api/**/models/` folder. Every JavaScript or JS
|
||||
If you are just starting out it is very convenient to generate some models with the Content Type Builder, directly in the admin interface. You can then review the generated model mappings on the code level. The UI takes over a lot of validation tasks and gives you a fast feeling for available features.
|
||||
:::
|
||||
|
||||
Use the CLI, and run the following command `strapi generate:model user firstname:string lastname:string`. Read the [CLI documentation](../cli/CLI.md) for more information.
|
||||
Use the CLI, and run the following command `strapi generate:model restaurant name:string description:text`. Read the [CLI documentation](../cli/CLI.md) for more information.
|
||||
|
||||
This will create two files located at `./api/user/models`:
|
||||
This will create two files located at `./api/restaurant/models`:
|
||||
|
||||
- `User.settings.json`: contains the list of attributes and settings. The JSON format makes the file easily editable.
|
||||
- `User.js`: imports `User.settings.json` and extends it with additional settings and lifecycle callbacks.
|
||||
- `Restaurant.settings.json`: contains the list of attributes and settings. The JSON format makes the file easily editable.
|
||||
- `Restaurant.js`: imports `Restaurant.settings.json` and extends it with additional settings and lifecycle callbacks.
|
||||
|
||||
::: note
|
||||
when you create a new API using the CLI (`strapi generate:api <name>`), a model is automatically created.
|
||||
@ -76,18 +78,18 @@ Additional settings can be set on models:
|
||||
- `collectionName` (string) - Collection's name (or table's name) in which the data should be stored.
|
||||
- `globalId` (string) -Global variable name for this model (case-sensitive).
|
||||
|
||||
**Path —** `User.settings.json`.
|
||||
**Path —** `Restaurant.settings.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"connection": "mongo",
|
||||
"collectionName": "Users_v1",
|
||||
"globalId": "Users",
|
||||
"collectionName": "Restaurants_v1",
|
||||
"globalId": "Restaurants",
|
||||
"attributes": {}
|
||||
}
|
||||
```
|
||||
|
||||
In this example, the model `User` will be accessible through the `Users` global variable. The data will be stored in the `Users_v1` collection or table and the model will use the `mongo` connection defined in `./config/environments/**/database.json`
|
||||
In this example, the model `Restaurant` will be accessible through the `Restaurants` global variable. The data will be stored in the `Restaurants_v1` collection or table and the model will use the `mongo` connection defined in `./config/environments/**/database.json`
|
||||
|
||||
::: note
|
||||
The `connection` value can be changed whenever you want, but you should be aware that there is no automatic data migration process. Also if the new connection doesn't use the same ORM you will have to rewrite your queries.
|
||||
@ -101,12 +103,12 @@ The info key on the model-json states information about the model. This informat
|
||||
- `description`: The description of the model.
|
||||
- `mainField`: Determines which model-attribute is shown when displaying the model.
|
||||
|
||||
**Path —** `User.settings.json`.
|
||||
**Path —** `Restaurant.settings.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"info": {
|
||||
"name": "user",
|
||||
"name": "restaurant",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
@ -137,6 +139,7 @@ The following types are currently available:
|
||||
|
||||
- `string`
|
||||
- `text`
|
||||
- `richtext`
|
||||
- `integer`
|
||||
- `biginteger`
|
||||
- `float`
|
||||
@ -172,45 +175,24 @@ To improve the Developer eXperience when developing or using the administration
|
||||
|
||||
### Example
|
||||
|
||||
**Path —** `User.settings.json`.
|
||||
**Path —** `Restaurant.settings.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"connection": "default",
|
||||
"info": {
|
||||
"name": "user",
|
||||
"description": "This represents the User Model",
|
||||
"mainField": "email"
|
||||
},
|
||||
...
|
||||
"attributes": {
|
||||
"firstname": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastname": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "email",
|
||||
"required": true,
|
||||
"title": {
|
||||
"type": "string",
|
||||
"min": 3,
|
||||
"max": 99,
|
||||
"unique": true
|
||||
},
|
||||
"password": {
|
||||
"type": "password",
|
||||
"required": true,
|
||||
"private": true
|
||||
"description": {
|
||||
"default": "My descrioption",
|
||||
"type": "text",
|
||||
"required": true
|
||||
},
|
||||
"about": {
|
||||
"type": "description"
|
||||
},
|
||||
"age": {
|
||||
"type": "integer",
|
||||
"min": 18,
|
||||
"max": 99,
|
||||
"index": true
|
||||
},
|
||||
"birthday": {
|
||||
"type": "date"
|
||||
}
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -243,21 +225,6 @@ A `pet` can be owned by someone (a `user`).
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/pet/controllers/Pet.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findPetsWithOwners: async ctx => {
|
||||
// Retrieve the list of pets with their owners.
|
||||
const pets = Pet.find().populate('owner');
|
||||
|
||||
// Send the list of pets.
|
||||
ctx.body = pets;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
@ -309,36 +276,6 @@ A `user` can have one `address`. And this address is only related to this `user`
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/user/controllers/User.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findUsersWithAddresses: async ctx => {
|
||||
// Retrieve the list of users with their addresses.
|
||||
const users = User.find().populate('address');
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = users;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/adress/controllers/Address.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findArticlesWithUsers: async ctx => {
|
||||
// Retrieve the list of addresses with their users.
|
||||
const articles = Address.find().populate('user');
|
||||
|
||||
// Send the list of addresses.
|
||||
ctx.body = addresses;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
@ -390,36 +327,6 @@ A `user` can have many `articles`, and an `article` can be related to one `user`
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/user/controllers/User.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findUsersWithArticles: async ctx => {
|
||||
// Retrieve the list of users with their articles.
|
||||
const users = User.find().populate('articles');
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = users;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/article/controllers/Article.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findArticlesWithAuthors: async ctx => {
|
||||
// Retrieve the list of articles with their authors.
|
||||
const articles = Article.find().populate('author');
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = articles;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Examples**
|
||||
|
||||
```js
|
||||
@ -486,36 +393,6 @@ A `product` can be related to many `categories`, so a `category` can have many `
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/product/controllers/Product.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findProductsWithCategories: async ctx => {
|
||||
// Retrieve the list of products.
|
||||
const products = Product.find().populate('categories');
|
||||
|
||||
// Send the list of products.
|
||||
ctx.body = products;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/category/controllers/Category.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findCategoriesWithProducts: async ctx => {
|
||||
// Retrieve the list of categories.
|
||||
const categories = Category.find().populate('products');
|
||||
|
||||
// Send the list of categories.
|
||||
ctx.body = categories;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
@ -644,102 +521,6 @@ A `Image` model might belongs to many either `Article` models or a `Product` mod
|
||||
}
|
||||
```
|
||||
|
||||
**Path —** `./api/image/controllers/Image.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findFiles: async ctx => {
|
||||
// Retrieve the list of images with the Article or Product entries related to them.
|
||||
const images = Images.find().populate('related');
|
||||
|
||||
/*
|
||||
[{
|
||||
"_id": "5a81b0fa8c063a53298a934a",
|
||||
"url": "http://....",
|
||||
"name": "john_doe_avatar.png",
|
||||
"related": [{
|
||||
"_id": "5a81b0fa8c063a5393qj934a",
|
||||
"title": "John Doe is awesome",
|
||||
"description": "..."
|
||||
}, {
|
||||
"_id": "5a81jei389ns5abd75f79c",
|
||||
"name": "A simple chair",
|
||||
"description": "..."
|
||||
}]
|
||||
}]
|
||||
*/
|
||||
|
||||
// Send the list of files.
|
||||
ctx.body = images;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/article/controllers/Article.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findArticlesWithAvatar: async ctx => {
|
||||
// Retrieve the list of articles with the avatar (image).
|
||||
const articles = Article.find().populate('avatar');
|
||||
|
||||
/*
|
||||
[{
|
||||
"_id": "5a81b0fa8c063a5393qj934a",
|
||||
"title": "John Doe is awesome",
|
||||
"description": "...",
|
||||
"avatar": {
|
||||
"_id": "5a81b0fa8c063a53298a934a",
|
||||
"url": "http://....",
|
||||
"name": "john_doe_avatar.png"
|
||||
}
|
||||
}]
|
||||
*/
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = articles;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Path —** `./api/product/controllers/Product.js`.
|
||||
|
||||
```js
|
||||
// Mongoose example
|
||||
module.exports = {
|
||||
findProductWithPictures: async ctx => {
|
||||
// Retrieve the list of products with the pictures (images).
|
||||
const products = Product.find().populate('pictures');
|
||||
|
||||
/*
|
||||
[{
|
||||
"_id": "5a81jei389ns5abd75f79c",
|
||||
"name": "A simple chair",
|
||||
"description": "...",
|
||||
"pictures": [{
|
||||
"_id": "5a81b0fa8c063a53298a934a",
|
||||
"url": "http://....",
|
||||
"name": "chair_position_1.png"
|
||||
}, {
|
||||
"_id": "5a81d22bee1ad45abd75f79c",
|
||||
"url": "http://....",
|
||||
"name": "chair_position_2.png"
|
||||
}, {
|
||||
"_id": "5a81d232ee1ad45abd75f79e",
|
||||
"url": "http://....",
|
||||
"name": "chair_position_3.png"
|
||||
}]
|
||||
}]
|
||||
*/
|
||||
|
||||
// Send the list of users.
|
||||
ctx.body = products;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
#### Database implementation
|
||||
|
||||
If you're using MongoDB as a database, you don't need to do anything. Everything is natively handled by Strapi. However, to implement a polymorphic relationship with SQL databases, you need to create two tables.
|
||||
@ -811,7 +592,7 @@ CREATE TABLE `image_morph` (
|
||||
|
||||
::: warning
|
||||
The life cycle functions are based on the ORM life cycle and not on the strapi request.
|
||||
We are currently woking on it to make it easier to use and understand.
|
||||
We are currently working on it to make it easier to use and understand.
|
||||
Please check [this issue](https://github.com/strapi/strapi/issues/1443) on GitHub.
|
||||
:::
|
||||
|
||||
|
107
docs/3.0.0-beta.x/guides/slug.md
Normal file
107
docs/3.0.0-beta.x/guides/slug.md
Normal file
@ -0,0 +1,107 @@
|
||||
# Create a slug system
|
||||
|
||||
This guide will explain how to create a slug system for a Post, Article or any Content Type you want.
|
||||
|
||||
## Create attributes
|
||||
|
||||
To start building your slug system you need a `string` field as a **base** for your slug, in this example we will use `title`.
|
||||
|
||||
You will also need another `string` field that contains the slugified value of your `title`, in this case we will use `slug`.
|
||||
|
||||

|
||||
|
||||
## Configure the layout for the content editor
|
||||
|
||||
Let's configure the layout of the **edit page** to make it more user friendly for the content editor.
|
||||
|
||||
- Click on the **Content Manager** link in the left menu.
|
||||
- Then on the `Article` Content Type.
|
||||
- And finally on the **Edit View** tab.
|
||||
|
||||
Here we will be able to setup the `slug` field.
|
||||
|
||||
- Click on the `slug` field.
|
||||
- At the bottom of the page, edit the **placeholder** value to `Generated automatically based on the title`.
|
||||
- And click **OFF** for **Editable field** option.
|
||||
- Don't forget to save your updates.
|
||||
|
||||
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
|
||||
|
||||
::: tab "Edit View before" id="before"
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
::: tab "Edit View after" id="after"
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
::: tab "Edit View configuration" id="config"
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Auto create/update the `slug` attribute
|
||||
|
||||
For that you will have to install `slugify` node module in your application.
|
||||
|
||||
When it's done, you have to update the life cycle of the **Article** Content Type to auto complete the `slug` field.
|
||||
|
||||
**Path —** `./api/article/models/Article.js`
|
||||
|
||||
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
|
||||
|
||||
::: tab "Mongoose" id="mongoose"
|
||||
|
||||
```js
|
||||
const slugify = require('slugify');
|
||||
|
||||
module.exports = {
|
||||
beforeSave: async model => {
|
||||
if (model.title) {
|
||||
model.slug = slugify(model.title);
|
||||
}
|
||||
},
|
||||
beforeUpdate: async model => {
|
||||
if (model.getUpdate().title) {
|
||||
model.update({
|
||||
slug: slugify(model.getUpdate().title),
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: tab "Bookshelf" id="bookshelf"
|
||||
|
||||
```js
|
||||
const slugify = require('slugify');
|
||||
|
||||
module.exports = {
|
||||
beforeSave: async (model, attrs, options) => {
|
||||
if (options.method === 'insert' && attrs.title) {
|
||||
model.set('slug', slugify(attrs.title));
|
||||
} else if (options.method === 'update' && attrs.title) {
|
||||
attrs.slug = slugify(attrs.title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Fetch article by `slug`
|
||||
|
||||
Then you will have to be able to fetch your **Articles** by this slug.
|
||||
|
||||
You will be able to find your articles by slug with this request `GET /articles?slug=my-article-slug`
|
||||
```
|
97
docs/3.0.0-beta.x/guides/update-version.md
Normal file
97
docs/3.0.0-beta.x/guides/update-version.md
Normal file
@ -0,0 +1,97 @@
|
||||
# Update Strapi version
|
||||
|
||||
How to upgrade your application to the latest version of Strapi.
|
||||
|
||||
## Upgrading your dependencies
|
||||
|
||||
Start by upgrading all your strapi package version.
|
||||
|
||||
For example moving from `3.0.0-beta.16` to `3.0.0-beta.17`
|
||||
|
||||
:::: tabs cache-lifetime="10" :options="{ useUrlFragment: false }"
|
||||
|
||||
::: tab "Before - 3.0.0-beta.16" id="3.0.0-beta.16"
|
||||
|
||||
```json
|
||||
{
|
||||
//...
|
||||
"dependencies": {
|
||||
"strapi": "3.0.0-beta.16",
|
||||
"strapi-admin": "3.0.0-beta.16",
|
||||
"strapi-hook-bookshelf": "3.0.0-beta.16",
|
||||
"strapi-hook-knex": "3.0.0-beta.16",
|
||||
"strapi-plugin-content-manager": "3.0.0-beta.16",
|
||||
"strapi-plugin-content-type-builder": "3.0.0-beta.16",
|
||||
"strapi-plugin-email": "3.0.0-beta.16",
|
||||
"strapi-plugin-graphql": "3.0.0-beta.16",
|
||||
"strapi-plugin-settings-manager": "3.0.0-beta.16",
|
||||
"strapi-plugin-upload": "3.0.0-beta.16",
|
||||
"strapi-plugin-users-permissions": "3.0.0-beta.16",
|
||||
"strapi-utils": "3.0.0-beta.16"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: tab "After - 3.0.0-beta.17" id="3.0.0-beta.17"
|
||||
|
||||
```json
|
||||
{
|
||||
//...
|
||||
"dependencies": {
|
||||
"strapi": "3.0.0-beta.17",
|
||||
"strapi-admin": "3.0.0-beta.17",
|
||||
"strapi-hook-bookshelf": "3.0.0-beta.17",
|
||||
"strapi-hook-knex": "3.0.0-beta.17",
|
||||
"strapi-plugin-content-manager": "3.0.0-beta.17",
|
||||
"strapi-plugin-content-type-builder": "3.0.0-beta.17",
|
||||
"strapi-plugin-email": "3.0.0-beta.17",
|
||||
"strapi-plugin-graphql": "3.0.0-beta.17",
|
||||
"strapi-plugin-settings-manager": "3.0.0-beta.17",
|
||||
"strapi-plugin-upload": "3.0.0-beta.17",
|
||||
"strapi-plugin-users-permissions": "3.0.0-beta.17",
|
||||
"strapi-utils": "3.0.0-beta.17"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
Then run either `yarn install` or `npm install` to install the specified version.
|
||||
|
||||
::: note
|
||||
If the operation doesn't work, you should probably remove your `yarn.lock` or `package-lock.json`. And if it still not work let's run the hard mode `rm -Rf node_modules`
|
||||
:::
|
||||
|
||||
## Building your administration panel
|
||||
|
||||
New release can introduces changes to the administration panel that require a rebuild.
|
||||
|
||||
Start by deleting your current build:
|
||||
|
||||
```bash
|
||||
rm -rf build
|
||||
```
|
||||
|
||||
Build the administration panel:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
# or
|
||||
npm run build
|
||||
```
|
||||
|
||||
::: note
|
||||
If the operation doesn't work, you should probably remove the `.cache` folder too.
|
||||
:::
|
||||
|
||||
## Migration guides
|
||||
|
||||
Sometimes Strapi introduces changes that need more than just the previous updates.
|
||||
|
||||
That is the reason of the [Migration Guide](../migration-guide/README.md) page.
|
||||
|
||||
Just make sure when you update your version that a migration guide exist or not.
|
Loading…
x
Reference in New Issue
Block a user